feat: jump to league for current season

This commit is contained in:
TrèsAbhi committed 2023-11-08 11:16:51 -06:00
1 parent 212aee0373
commit d08949c597
3 files changed
+105 -108

No files matched your search

+90 -97
View File
@@ -58,6 +58,7 @@ export default function Page() {
const usernameCache = useUsernameCache(); const usernameCache = useUsernameCache();
const clanCache = useClanCache(); const clanCache = useClanCache();
const [region, setRegion] = useState<Region>('com'); const [region, setRegion] = useState<Region>('com');
const leaguePositionCache = useRef<Record<number, number>>({});
// null being the latest season // null being the latest season
const [season, setSeason] = useState<null | number>(null); const [season, setSeason] = useState<null | number>(null);
const { data: ratingsInfo } = useSWR( const { data: ratingsInfo } = useSWR(
@@ -110,39 +111,36 @@ export default function Page() {
useEffect(() => { useEffect(() => {
// league caching // league caching
if (season === null) { if (season === null) {
Promise.all( (async () => {
range(0, 4).map(async (league: number) => { const newUsernameCache: Record<number, string> = {};
const leaguePlayers = await getRatingsLeague(region, league); const newClanCache: Record<number, string> = {};
useUsernameCache.setState( const results = await Promise.all(
produce((draft: UsernameCache) => { range(0, 5).map(async (league: number) => {
leaguePlayers.result.forEach((player) => { const leaguePlayers = await getRatingsLeague(region, league);
draft[region][player.spa_id] = player.nickname;
});
}),
);
useClanCache.setState(
produce((draft: ClanCache) => {
leaguePlayers.result.forEach((player) => {
draft[region][player.spa_id] = player.clan_tag;
});
}),
);
return leaguePlayers.result.reduce< leaguePositionCache.current[league] =
Record<number, BlitzkriegRatingsLeaderboardEntry> leaguePlayers.result[0].number - 1;
>(
(accumulator, player) => ({
...accumulator,
[player.number - 1]: { leaguePlayers.result.forEach((player) => {
id: player.spa_id, newUsernameCache[player.spa_id] = player.nickname;
score: player.score, newClanCache[player.spa_id] = player.clan_tag;
} satisfies BlitzkriegRatingsLeaderboardEntry, });
}),
{}, return leaguePlayers.result.reduce<
); Record<number, BlitzkriegRatingsLeaderboardEntry>
}), >(
).then((results) => { (accumulator, player) => ({
...accumulator,
[player.number - 1]: {
id: player.spa_id,
score: player.score,
} satisfies BlitzkriegRatingsLeaderboardEntry,
}),
{},
);
}),
);
const newPlayers = results.reduce< const newPlayers = results.reduce<
Record<number, BlitzkriegRatingsLeaderboardEntry> Record<number, BlitzkriegRatingsLeaderboardEntry>
>( >(
@@ -154,13 +152,59 @@ export default function Page() {
); );
setPlayers(newPlayers); setPlayers(newPlayers);
}); useUsernameCache.setState((old) => ({
...old,
[region]: { ...old[region], ...newUsernameCache },
}));
useClanCache.setState((old) => ({
...old,
[region]: { ...old[region], ...newClanCache },
}));
})();
} else { } else {
getArchivedRatingsLeaderboard(region, season).then((result) => getArchivedRatingsLeaderboard(region, season).then((result) =>
setPlayers({ ...result }), setPlayers({ ...result }),
); );
} }
}, []); }, []);
async function cacheNeighbors(id: number, size: number) {
const { neighbors } = await getRatingsNeighbors(region, id, size);
setPlayers(
produce((draft) => {
draft = draft ?? {};
neighbors.forEach((neighbor) => {
draft![neighbor.number - 1] = {
id: neighbor.spa_id,
score: neighbor.score,
} satisfies BlitzkriegRatingsLeaderboardEntry;
});
}),
);
useUsernameCache.setState(
produce((draft: UsernameCache) => {
neighbors.forEach((neighbor) => {
if (neighbor.nickname) {
draft[region][neighbor.spa_id] = neighbor.nickname;
}
});
}),
);
useClanCache.setState(
produce((draft: ClanCache) => {
neighbors.forEach((neighbor) => {
if (neighbor.clan_tag) {
draft[region][neighbor.spa_id] = neighbor.clan_tag;
}
});
}),
);
}
useEffect(() => { useEffect(() => {
// TODO: caches twice on initial load // TODO: caches twice on initial load
if (!players || !ratingsInfo || ratingsInfo?.detail) return; if (!players || !ratingsInfo || ratingsInfo?.detail) return;
@@ -172,42 +216,7 @@ export default function Page() {
const middleId = players[middleIndex].id; const middleId = players[middleIndex].id;
getRatingsNeighbors(region, middleId, rowsPerPage * 3).then( cacheNeighbors(middleId, rowsPerPage * 3);
({ neighbors }) => {
setPlayers(
produce((draft) => {
draft = draft ?? {};
neighbors.forEach((neighbor) => {
draft![neighbor.number - 1] = {
id: neighbor.spa_id,
score: neighbor.score,
} satisfies BlitzkriegRatingsLeaderboardEntry;
});
}),
);
useUsernameCache.setState(
produce((draft: UsernameCache) => {
neighbors.forEach((neighbor) => {
if (neighbor.nickname) {
draft[region][neighbor.spa_id] = neighbor.nickname;
}
});
}),
);
useClanCache.setState(
produce((draft: ClanCache) => {
neighbors.forEach((neighbor) => {
if (neighbor.clan_tag) {
draft[region][neighbor.spa_id] = neighbor.clan_tag;
}
});
}),
);
},
);
} else { } else {
const ids = range( const ids = range(
Math.max(0, (page - 1) * rowsPerPage), Math.max(0, (page - 1) * rowsPerPage),
@@ -244,7 +253,7 @@ export default function Page() {
}); });
} }
} }
}, [page, players]); }, [page]);
const handleJumpToPosition = () => { const handleJumpToPosition = () => {
if (!players || !ratingsInfo || ratingsInfo?.detail) return; if (!players || !ratingsInfo || ratingsInfo?.detail) return;
@@ -509,34 +518,18 @@ export default function Page() {
<Button <Button
onClick={async () => { onClick={async () => {
if (season === null) { if (season === null) {
// that's already done const position =
const leaguePlayers = await getRatingsLeague( leaguePositionCache.current[jumpToLeague];
region, const newPage = Math.floor(position / rowsPerPage);
jumpToLeague,
);
useUsernameCache.setState( setPage(newPage);
produce((draft: UsernameCache) => { if (players) {
leaguePlayers.result.forEach((player) => { setHighlightedPlayerId(players[position].id);
draft[region][player.spa_id] = player.nickname; cacheNeighbors(
}); players[position].id,
}), rowsPerPage * 3,
); );
useClanCache.setState( }
produce((draft: ClanCache) => {
leaguePlayers.result.forEach((player) => {
draft[region][player.spa_id] = player.clan_tag;
});
}),
);
leaguePlayers.result.map(
(player) =>
({
id: player.spa_id,
score: player.score,
}) satisfies BlitzkriegRatingsLeaderboardEntry,
);
} else { } else {
if (!ratingsInfo || ratingsInfo.detail || !players) if (!ratingsInfo || ratingsInfo.detail || !players)
return; return;
@@ -663,7 +656,7 @@ export default function Page() {
: `Loading player...` : `Loading player...`
} }
position={index + 1} position={index + 1}
score={players![index]?.score ?? 0} score={players![index]?.score}
clan={ clan={
players![index] players![index]
? clanCache[region][players![index].id] ? clanCache[region][players![index].id]
+13 -11
View File
@@ -5,7 +5,7 @@ import { theme } from '../../../stitches.config';
export interface ItemProps extends ComponentProps<'div'> { export interface ItemProps extends ComponentProps<'div'> {
position: number; position: number;
deltaPosition?: number; deltaPosition?: number;
score: number; score?: number;
deltaScore?: number; deltaScore?: number;
reward?: RatingsReward; reward?: RatingsReward;
nickname: string; nickname: string;
@@ -188,16 +188,18 @@ export function Item({
} }
/> />
)} )}
<span {score !== undefined && (
style={{ <span
color: highlight style={{
? theme.colors.textHighContrast_blue color: highlight
: theme.colors.textHighContrast, ? theme.colors.textHighContrast_blue
fontSize: 16, : theme.colors.textHighContrast,
}} fontSize: 16,
> }}
{score.toLocaleString()} >
</span> {score.toLocaleString()}
</span>
)}
</div> </div>
</div> </div>
); );
+2
View File
@@ -4,4 +4,6 @@ export function withCORSProxy(url: string) {
return context === 'website' return context === 'website'
? `https://corsproxy.io/?${encodeURIComponent(url)}` ? `https://corsproxy.io/?${encodeURIComponent(url)}`
: url; : url;
// `https://api.allorigins.win/raw?url=${encodeURIComponent(url)}`;
} }