added option for impact route to return a specific map with ?mapName parameter
This commit is contained in:
@@ -8,6 +8,17 @@ export async function GET(req: NextRequest) {
|
|||||||
const directionParam = req.nextUrl.searchParams.get('direction');
|
const directionParam = req.nextUrl.searchParams.get('direction');
|
||||||
const offset = Math.max(0, Number(req.nextUrl.searchParams.get('offset')) || 0);
|
const offset = Math.max(0, Number(req.nextUrl.searchParams.get('offset')) || 0);
|
||||||
|
|
||||||
|
// Accept either `mapName=foo` or `mapNames=foo,bar` (also tolerate
|
||||||
|
// repeated `mapName` params), so individual maps can be looked up
|
||||||
|
// directly instead of paging through the whole leaderboard.
|
||||||
|
const mapNames = [
|
||||||
|
...req.nextUrl.searchParams.getAll('mapName'),
|
||||||
|
...req.nextUrl.searchParams.getAll('mapNames'),
|
||||||
|
]
|
||||||
|
.flatMap((v) => v.split(','))
|
||||||
|
.map((v) => v.trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
const sortBy = sortByParam === 'popularity' ? 'popularity' : 'impact';
|
const sortBy = sortByParam === 'popularity' ? 'popularity' : 'impact';
|
||||||
// Impact defaults to ascending (worst/most population-harming first, the
|
// Impact defaults to ascending (worst/most population-harming first, the
|
||||||
// whole point of the feature); popularity defaults to descending (most
|
// whole point of the feature); popularity defaults to descending (most
|
||||||
@@ -16,8 +27,15 @@ export async function GET(req: NextRequest) {
|
|||||||
? directionParam
|
? directionParam
|
||||||
: sortBy === 'popularity' ? 'desc' : 'asc';
|
: sortBy === 'popularity' ? 'desc' : 'asc';
|
||||||
|
|
||||||
const maps = await getMapImpactLeaderboard(sortBy, direction, PAGE_SIZE, offset);
|
const maps = await getMapImpactLeaderboard(
|
||||||
const hasMore = maps.length === PAGE_SIZE;
|
sortBy,
|
||||||
|
direction,
|
||||||
|
PAGE_SIZE,
|
||||||
|
offset,
|
||||||
|
mapNames.length > 0 ? mapNames : undefined,
|
||||||
|
);
|
||||||
|
// Pagination only applies when not filtering by name (see getMapImpactLeaderboard).
|
||||||
|
const hasMore = mapNames.length === 0 && maps.length === PAGE_SIZE;
|
||||||
|
|
||||||
return NextResponse.json({ maps, hasMore });
|
return NextResponse.json({ maps, hasMore });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,14 +235,23 @@ export async function getMapImpactLeaderboard(
|
|||||||
direction: 'asc' | 'desc',
|
direction: 'asc' | 'desc',
|
||||||
limit = 50,
|
limit = 50,
|
||||||
offset = 0,
|
offset = 0,
|
||||||
|
mapNames?: string[],
|
||||||
): Promise<MapImpactSummary[]> {
|
): Promise<MapImpactSummary[]> {
|
||||||
const all = await getMapImpactStatsCached();
|
const all = await getMapImpactStatsCached();
|
||||||
|
const filtered = mapNames && mapNames.length > 0
|
||||||
|
? (() => {
|
||||||
|
const wanted = new Set(mapNames.map((n) => n.toLowerCase()));
|
||||||
|
return all.filter((m) => wanted.has(m.map_name.toLowerCase()));
|
||||||
|
})()
|
||||||
|
: all;
|
||||||
const sign = direction === 'asc' ? 1 : -1;
|
const sign = direction === 'asc' ? 1 : -1;
|
||||||
const sorted = [...all].sort((a, b) => {
|
const sorted = [...filtered].sort((a, b) => {
|
||||||
const av = sortBy === 'popularity' ? a.times_played : a.avg_net_change ?? 0;
|
const av = sortBy === 'popularity' ? a.times_played : a.avg_net_change ?? 0;
|
||||||
const bv = sortBy === 'popularity' ? b.times_played : b.avg_net_change ?? 0;
|
const bv = sortBy === 'popularity' ? b.times_played : b.avg_net_change ?? 0;
|
||||||
if (av !== bv) return sign * (av - bv);
|
if (av !== bv) return sign * (av - bv);
|
||||||
return b.times_played - a.times_played; // stable tiebreaker, matches old ORDER BY ..., times_played DESC
|
return b.times_played - a.times_played; // stable tiebreaker, matches old ORDER BY ..., times_played DESC
|
||||||
});
|
});
|
||||||
return sorted.slice(offset, offset + limit);
|
// When specific map names are requested, return all matches rather than
|
||||||
|
// paginating — the caller asked for those exact maps, not a page of them.
|
||||||
|
return mapNames && mapNames.length > 0 ? sorted : sorted.slice(offset, offset + limit);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user