diff --git a/src/main/java/org/patinanetwork/codebloom/api/leaderboard/LeaderboardController.java b/src/main/java/org/patinanetwork/codebloom/api/leaderboard/LeaderboardController.java index 3223a4393..584439a74 100644 --- a/src/main/java/org/patinanetwork/codebloom/api/leaderboard/LeaderboardController.java +++ b/src/main/java/org/patinanetwork/codebloom/api/leaderboard/LeaderboardController.java @@ -10,6 +10,7 @@ import jakarta.servlet.http.HttpServletRequest; import java.util.List; import java.util.Optional; +import java.util.Set; import org.patinanetwork.codebloom.common.components.LeaderboardManager; import org.patinanetwork.codebloom.common.db.models.leaderboard.Leaderboard; import org.patinanetwork.codebloom.common.db.models.user.UserWithScore; @@ -99,6 +100,8 @@ public ResponseEntity>>> getLeaderbo @Parameter(description = "Discord name", example = "tahmid") @RequestParam(required = false, defaultValue = "") final String query, + @Parameter(description = "Filter for users by institution") @RequestParam(required = false) + final Set filters, @Parameter(description = "Filter for Patina users") @RequestParam(required = false, defaultValue = "false") final boolean patina, @Parameter(description = "Filter for Hunter College users") @@ -133,22 +136,31 @@ public ResponseEntity>>> getLeaderbo final int parsedPageSize = Math.min(pageSize, MAX_LEADERBOARD_PAGE_SIZE); - LeaderboardFilterOptions options = LeaderboardFilterOptions.builder() + final LeaderboardFilterOptions options; + + final Set normalizedFilters = filters == null + ? Set.of() + : filters.stream() + .filter(java.util.Objects::nonNull) + .map(s -> s.trim().toLowerCase()) + .collect(java.util.stream.Collectors.toSet()); + + options = LeaderboardFilterOptions.builder() .page(page) .pageSize(parsedPageSize) .query(query) - .patina(patina) - .hunter(hunter) - .nyu(nyu) - .baruch(baruch) - .rpi(rpi) - .gwc(gwc) - .sbu(sbu) - .ccny(ccny) - .columbia(columbia) - .cornell(cornell) - .bmcc(bmcc) - .mhcplusplus(mhcplusplus) + .patina(patina || normalizedFilters.contains("patina")) + .hunter(hunter || normalizedFilters.contains("hunter")) + .nyu(nyu || normalizedFilters.contains("nyu")) + .baruch(baruch || normalizedFilters.contains("baruch")) + .rpi(rpi || normalizedFilters.contains("rpi")) + .gwc(gwc || normalizedFilters.contains("gwc")) + .sbu(sbu || normalizedFilters.contains("sbu")) + .ccny(ccny || normalizedFilters.contains("ccny")) + .columbia(columbia || normalizedFilters.contains("columbia")) + .cornell(cornell || normalizedFilters.contains("cornell")) + .bmcc(bmcc || normalizedFilters.contains("bmcc")) + .mhcplusplus(mhcplusplus || normalizedFilters.contains("mhcplusplus")) .build(); Page> createdPage = diff --git a/src/test/java/org/patinanetwork/codebloom/api/leaderboard/LeaderboardControllerTest.java b/src/test/java/org/patinanetwork/codebloom/api/leaderboard/LeaderboardControllerTest.java index 678f4a0ed..a46258d3f 100644 --- a/src/test/java/org/patinanetwork/codebloom/api/leaderboard/LeaderboardControllerTest.java +++ b/src/test/java/org/patinanetwork/codebloom/api/leaderboard/LeaderboardControllerTest.java @@ -1,11 +1,15 @@ package org.patinanetwork.codebloom.api.leaderboard; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; import java.time.LocalDateTime; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.UUID; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -57,6 +61,7 @@ void testGetLeaderboardUsersByIdMhcPlusPlus() { PAGE, PAGE_SIZE, "", + Set.of(), false, false, false, @@ -138,6 +143,7 @@ void capsPageSize() { 1, 999, "", + Set.of(), false, false, false, @@ -167,6 +173,7 @@ void passesAllFilters() { 2, 10, "tahmid", + Set.of(), true /* patina */, true /* hunter */, true /* nyu */, @@ -203,6 +210,108 @@ void passesAllFilters() { assertTrue(opts.isMhcplusplus()); } + @Test + @DisplayName("passes all filter flags through to LeaderboardFilterOptions through set") + void passesAllFiltersThroughSet() { + leaderboardController.getLeaderboardUsersById( + LEADERBOARD_ID, + 2, + 10, + "tahmid", + Set.of( + "patina", + "hunter", + "nyu", + "baruch", + "rpi", + "gwc", + "sbu", + "ccny", + "columbia", + "cornell", + "bmcc", + "mhcplusplus"), + false /* patina */, + false /* hunter */, + false /* nyu */, + false /* baruch */, + false /* rpi */, + false /* gwc */, + false /* sbu */, + false /* ccny */, + false /* columbia */, + false /* cornell */, + false /* bmcc */, + false /* mhc++ */, + true /* globalIndex */, + null); + + ArgumentCaptor captor = ArgumentCaptor.forClass(LeaderboardFilterOptions.class); + verify(leaderboardManager).getLeaderboardUsers(eq(LEADERBOARD_ID), captor.capture(), eq(true)); + + var opts = captor.getValue(); + assertEquals(2, opts.getPage()); + assertEquals(10, opts.getPageSize()); + assertEquals("tahmid", opts.getQuery()); + assertTrue(opts.isPatina()); + assertTrue(opts.isHunter()); + assertTrue(opts.isNyu()); + assertTrue(opts.isBaruch()); + assertTrue(opts.isRpi()); + assertTrue(opts.isGwc()); + assertTrue(opts.isSbu()); + assertTrue(opts.isCcny()); + assertTrue(opts.isColumbia()); + assertTrue(opts.isCornell()); + assertTrue(opts.isBmcc()); + assertTrue(opts.isMhcplusplus()); + } + + @Test + @DisplayName("passes certain filter flags through to LeaderboardFilterOptions through set") + void passesCertainFiltersThroughSet() { + leaderboardController.getLeaderboardUsersById( + LEADERBOARD_ID, + 2, + 10, + "tahmid", + Set.of("patina", "hunter", "nyu", "baruch", "bmcc", "mhcplusplus"), + false /* patina */, + false /* hunter */, + false /* nyu */, + false /* baruch */, + false /* rpi */, + false /* gwc */, + false /* sbu */, + false /* ccny */, + false /* columbia */, + false /* cornell */, + false /* bmcc */, + false /* mhc++ */, + true /* globalIndex */, + null); + + ArgumentCaptor captor = ArgumentCaptor.forClass(LeaderboardFilterOptions.class); + verify(leaderboardManager).getLeaderboardUsers(eq(LEADERBOARD_ID), captor.capture(), eq(true)); + + var opts = captor.getValue(); + assertEquals(2, opts.getPage()); + assertEquals(10, opts.getPageSize()); + assertEquals("tahmid", opts.getQuery()); + assertTrue(opts.isPatina()); + assertTrue(opts.isHunter()); + assertTrue(opts.isNyu()); + assertTrue(opts.isBaruch()); + assertFalse(opts.isRpi()); + assertFalse(opts.isGwc()); + assertFalse(opts.isSbu()); + assertFalse(opts.isCcny()); + assertFalse(opts.isColumbia()); + assertFalse(opts.isCornell()); + assertTrue(opts.isBmcc()); + assertTrue(opts.isMhcplusplus()); + } + @Test @DisplayName("returns metadata for the most recent leaderboard") void returnsCurrentMetadata() {