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 3ec2f87d3..2a53d863d 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; @@ -93,6 +94,9 @@ public ResponseEntity> getLeaderboardMetadataByLead }) public ResponseEntity>>> getLeaderboardUsersById( @PathVariable final String leaderboardId, + @Parameter(description = "Comma-separated list of active filters.", example = "nyu,hunter,globalIndex") + @RequestParam(required = false) + final Set filters, @Parameter(description = "Page index", example = "1") @RequestParam(required = false, defaultValue = "1") final int page, @Parameter(description = "Page size (maximum of " + MAX_LEADERBOARD_PAGE_SIZE) @@ -133,29 +137,30 @@ public ResponseEntity>>> getLeaderbo final boolean globalIndex, final HttpServletRequest request) { FakeLag.sleep(800); - final int parsedPageSize = Math.min(pageSize, MAX_LEADERBOARD_PAGE_SIZE); + final Set activeFilters = filters != null ? filters : Set.of(); + final boolean useFilters = !activeFilters.isEmpty(); + final boolean globalIndexNew = useFilters ? activeFilters.contains("globalIndex") : globalIndex; - LeaderboardFilterOptions options = LeaderboardFilterOptions.builder() + final LeaderboardFilterOptions 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(useFilters ? activeFilters.contains("patina") : patina) + .hunter(useFilters ? activeFilters.contains("hunter") : hunter) + .nyu(useFilters ? activeFilters.contains("nyu") : nyu) + .baruch(useFilters ? activeFilters.contains("baruch") : baruch) + .rpi(useFilters ? activeFilters.contains("rpi") : rpi) + .gwc(useFilters ? activeFilters.contains("gwc") : gwc) + .sbu(useFilters ? activeFilters.contains("sbu") : sbu) + .ccny(useFilters ? activeFilters.contains("ccny") : ccny) + .columbia(useFilters ? activeFilters.contains("columbia") : columbia) + .cornell(useFilters ? activeFilters.contains("cornell") : cornell) + .bmcc(useFilters ? activeFilters.contains("bmcc") : bmcc) + .mhcplusplus(useFilters ? activeFilters.contains("mhcplusplus") : mhcplusplus) .build(); - Page> createdPage = - leaderboardManager.getLeaderboardUsers(leaderboardId, options, globalIndex); + leaderboardManager.getLeaderboardUsers(leaderboardId, options, globalIndexNew); return ResponseEntity.ok().body(ApiResponder.success("All leaderboards found!", 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 f386347cc..3d9d97eb1 100644 --- a/src/test/java/org/patinanetwork/codebloom/api/leaderboard/LeaderboardControllerTest.java +++ b/src/test/java/org/patinanetwork/codebloom/api/leaderboard/LeaderboardControllerTest.java @@ -6,6 +6,7 @@ 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; @@ -54,6 +55,7 @@ void setup() { void testGetLeaderboardUsersByIdMhcPlusPlus() { leaderboardController.getLeaderboardUsersById( LEADERBOARD_ID, + null, PAGE, PAGE_SIZE, "", @@ -135,6 +137,7 @@ void throws404WhenNotFound() { void capsPageSize() { leaderboardController.getLeaderboardUsersById( LEADERBOARD_ID, + null, 1, 999, "", @@ -164,6 +167,7 @@ void capsPageSize() { void passesAllFilters() { leaderboardController.getLeaderboardUsersById( LEADERBOARD_ID, + null, 2, 10, "tahmid", @@ -203,6 +207,96 @@ void passesAllFilters() { assertTrue(opts.isMhcplusplus()); } + @Test + @DisplayName("uses filters Set when provided, ignoring individual boolean params") + void usesFiltersSetWhenProvided() { + leaderboardController.getLeaderboardUsersById( + LEADERBOARD_ID, + Set.of("nyu", "hunter"), + PAGE, + PAGE_SIZE, + "", + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + null); + + ArgumentCaptor captor = ArgumentCaptor.forClass(LeaderboardFilterOptions.class); + verify(leaderboardManager).getLeaderboardUsers(eq(LEADERBOARD_ID), captor.capture(), eq(false)); + var opts = captor.getValue(); + assertTrue(opts.isNyu()); + assertTrue(opts.isHunter()); + assertFalse(opts.isPatina()); + } + + @Test + @DisplayName("sets globalIndex from filters Set when it contains globalIndex") + void setsGlobalIndexFromFiltersSet() { + leaderboardController.getLeaderboardUsersById( + LEADERBOARD_ID, + Set.of("nyu", "globalIndex"), + PAGE, + PAGE_SIZE, + "", + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + null); + + ArgumentCaptor captor = ArgumentCaptor.forClass(LeaderboardFilterOptions.class); + verify(leaderboardManager).getLeaderboardUsers(eq(LEADERBOARD_ID), captor.capture(), eq(true)); + assertTrue(captor.getValue().isNyu()); + } + + @Test + @DisplayName("falls back to boolean params when filters Set is empty") + void fallsBackToBooleansWhenFiltersEmpty() { + leaderboardController.getLeaderboardUsersById( + LEADERBOARD_ID, + Set.of(), + PAGE, + PAGE_SIZE, + "", + true, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + null); + + ArgumentCaptor captor = ArgumentCaptor.forClass(LeaderboardFilterOptions.class); + verify(leaderboardManager).getLeaderboardUsers(eq(LEADERBOARD_ID), captor.capture(), eq(false)); + assertTrue(captor.getValue().isPatina()); + } + @Test @DisplayName("returns metadata for the most recent leaderboard") void returnsCurrentMetadata() {