From 81aec6bad20a5629789a27b888745ec2afed062b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Wed, 8 Nov 2023 12:17:08 -0600 Subject: [PATCH] feat: search players for current season --- src/app/tools/ratings/page.tsx | 254 ++++++++++++++----- src/core/blitz/searchPlayersAcrossRegions.ts | 6 +- 2 files changed, 197 insertions(+), 63 deletions(-) diff --git a/src/app/tools/ratings/page.tsx b/src/app/tools/ratings/page.tsx index 172e4bf66..8257262d0 100644 --- a/src/app/tools/ratings/page.tsx +++ b/src/app/tools/ratings/page.tsx @@ -31,10 +31,15 @@ import { getClanAccountInfo } from '../../../core/blitz/getClanAccountInfo'; import getRatingsInfo from '../../../core/blitz/getRatingsInfo'; import { getRatingsLeague } from '../../../core/blitz/getRatingsLeague'; import { getRatingsNeighbors } from '../../../core/blitz/getRatingsNeighbors'; -import { AccountList } from '../../../core/blitz/searchPlayersAcrossRegions'; +import regionToRegionSubdomain from '../../../core/blitz/regionToRegionSubdomain'; +import { + AccountList, + AccountListItem, +} from '../../../core/blitz/searchPlayersAcrossRegions'; import { getArchivedLatestSeasonNumber } from '../../../core/blitzkrieg/getArchivedLatestSeasonNumber'; import getArchivedRatingsInfo from '../../../core/blitzkrieg/getArchivedRatingsInfo'; import { getArchivedRatingsLeaderboard } from '../../../core/blitzkrieg/getArchivedRatingsLeaderboard'; +import { withCORSProxy } from '../../../core/blitzkrieg/withCORSProxy'; import { noArrows } from './page.css'; const ROWS_OPTIONS = [5, 10, 15, 25, 30]; @@ -83,30 +88,9 @@ export default function Page() { ); const positionInput = useRef(null); const scoreInput = useRef(null); - const [searchResults, setSearchResults] = useState( - undefined, - ); - const handleSearchPlayerChange = debounce( - async (event: ChangeEvent) => { - const trimmedSearch = event.target.value.trim(); - - if (trimmedSearch) { - const encodedSearch = encodeURIComponent(trimmedSearch); - const accountList = await fetchBlitz( - `https://api.wotblitz.${region}/wotb/account/list/?application_id=${WARGAMING_APPLICATION_ID}&search=${encodedSearch}&limit=100`, - ); - - setSearchResults( - accountList.filter( - (searchedPlayer) => players && searchedPlayer.account_id in players, - ), - ); - } else { - setSearchResults(undefined); - } - }, - 500, - ); + const [searchResults, setSearchResults] = useState< + (AccountListItem & { number: number })[] | undefined + >(undefined); useEffect(() => { // league caching @@ -168,6 +152,12 @@ export default function Page() { } }, []); + useEffect(() => { + if (players !== null && 0 in players) { + cacheNeighbors(players[0].id, rowsPerPage * 3); + } + }, [players !== null && 0 in players]); + async function cacheNeighbors(id: number, size: number) { const { neighbors } = await getRatingsNeighbors(region, id, size); @@ -292,6 +282,7 @@ export default function Page() { (ratingsInfo && ratingsInfo.detail === undefined ? ratingsInfo?.count : 1) / rowsPerPage, ); + const [searchLoading, setSearchLoading] = useState(false); useEffect(() => { setPage(0); @@ -431,7 +422,6 @@ export default function Page() { { @@ -465,7 +455,6 @@ export default function Page() { { @@ -576,48 +565,193 @@ export default function Page() { ) => { + const trimmedSearch = event.target.value.trim(); + const encodedSearch = encodeURIComponent(trimmedSearch); + + if (trimmedSearch) { + if (season === null) { + setSearchLoading(true); + + const response = await fetch( + withCORSProxy( + `https://${regionToRegionSubdomain( + region, + )}.wotblitz.com/en/api/rating-leaderboards/search/?prefix=${encodedSearch}`, + ), + ); + const accountList = + (await response.json()) as Record< + number, + { + spa_id: number; + nickname: string; + clan_tag: string; + } & ( + | { + skip: true; + } + | { + skip: false; + mmr: number; + season_number: number; + calibrationBattlesLeft: number; + number: number; + updated_at: string; + neighbors: []; + } + ) + >; + const values = Object.values(accountList).filter( + (searchedPlayer) => !searchedPlayer.skip, + ); + const valuesWithTypes = + values as ((typeof values)[number] & { + skip: false; + })[]; + + setPlayers( + produce((draft: typeof players) => { + if (draft) { + values.map((player) => { + const playerWithTypes = + player as typeof player & { skip: false }; + draft[playerWithTypes.number - 1] = { + id: playerWithTypes.spa_id, + score: 0, + }; + }); + } + }), + ); + useUsernameCache.setState( + produce((draft: typeof usernameCache) => { + valuesWithTypes.forEach((searchedPlayer) => { + if (searchedPlayer.nickname) { + draft[region][searchedPlayer.spa_id] = + searchedPlayer.nickname; + } + }); + }), + ); + useClanCache.setState( + produce((draft: typeof clanCache) => { + valuesWithTypes.forEach((searchedPlayer) => { + if (searchedPlayer.clan_tag) { + draft[region][searchedPlayer.spa_id] = + searchedPlayer.clan_tag; + } + }); + }), + ); + setSearchResults( + valuesWithTypes.map((searchedPlayer) => ({ + account_id: searchedPlayer.spa_id, + nickname: searchedPlayer.nickname, + number: searchedPlayer.number, + })), + ); + setSearchLoading(false); + } else { + setSearchLoading(true); + const accountList = await fetchBlitz( + `https://api.wotblitz.${region}/wotb/account/list/?application_id=${WARGAMING_APPLICATION_ID}&search=${encodedSearch}&limit=100`, + ); + const playerKeys = Object.keys(players!); + + setSearchResults( + accountList + .filter( + (searchedPlayer) => + players && + searchedPlayer.account_id in players, + ) + .map((searchedPlayer) => ({ + ...searchedPlayer, + number: parseInt( + playerKeys.find( + (index) => + players![parseInt(index)].id === + searchedPlayer.account_id, + )!, + ), + })), + ); + setSearchLoading(false); + } + } else { + setSearchResults(undefined); + } + }, + 500, + )} placeholder="Search for player..." /> - {searchResults?.map((player) => ( - - + + ))} - const playerPage = Math.floor( - playerIndex! / rowsPerPage, - ); - - setPage(playerPage); - setHighlightedPlayerId(player.account_id); - }} - > - {player.nickname} - - - ))} - - {searchResults?.length === 0 && ( + {!searchLoading && searchResults?.length === 0 && ( + )} + + {!searchLoading && searchResults === undefined && ( + + )} + + {searchLoading && ( + )} diff --git a/src/core/blitz/searchPlayersAcrossRegions.ts b/src/core/blitz/searchPlayersAcrossRegions.ts index cfc61bb89..98dc76754 100644 --- a/src/core/blitz/searchPlayersAcrossRegions.ts +++ b/src/core/blitz/searchPlayersAcrossRegions.ts @@ -2,12 +2,12 @@ import { Region } from '../../constants/regions'; import { WARGAMING_APPLICATION_ID } from '../../constants/wargamingApplicationID'; import fetchBlitz from './fetchBlitz'; -interface Account { +export interface AccountListItem { nickname: string; account_id: number; } -export type AccountList = Account[]; -export type AccountListWithServer = (Account & { +export type AccountList = AccountListItem[]; +export type AccountListWithServer = (AccountListItem & { region: Region; })[];