diff --git a/packages/core/src/math/fisherYates.ts b/packages/core/src/math/fisherYates.ts new file mode 100644 index 000000000..74198bd7d --- /dev/null +++ b/packages/core/src/math/fisherYates.ts @@ -0,0 +1,8 @@ +export function fisherYates(array: Type) { + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; + } + + return array; +} diff --git a/packages/core/src/math/index.ts b/packages/core/src/math/index.ts index bb4a1859b..b8a2089a0 100644 --- a/packages/core/src/math/index.ts +++ b/packages/core/src/math/index.ts @@ -1,7 +1,8 @@ -export * from './axis'; -export * from './formatCompact'; -export * from './isNumber'; -export * from './NaNFallback'; -export * from './normalizeAngleRad'; -export * from './normalToEuler'; -export * from './numberToRomanNumeral'; +export * from "./axis"; +export * from "./fisherYates"; +export * from "./formatCompact"; +export * from "./isNumber"; +export * from "./NaNFallback"; +export * from "./normalizeAngleRad"; +export * from "./normalToEuler"; +export * from "./numberToRomanNumeral"; diff --git a/packages/website/src/components/PlaylistActions.tsx b/packages/website/src/components/PlaylistActions.tsx index 12fc319e9..3d8392122 100644 --- a/packages/website/src/components/PlaylistActions.tsx +++ b/packages/website/src/components/PlaylistActions.tsx @@ -1,3 +1,4 @@ +import { fisherYates } from "@blitzkit/core"; import { CaretDownIcon } from "@radix-ui/react-icons"; import { Button, Flex } from "@radix-ui/themes"; import { useLocale } from "../hooks/useLocale"; @@ -20,7 +21,14 @@ export function PlaylistActions() { {strings.website.tools.playlist.reset} - diff --git a/packages/website/src/components/PlaylistGenerator.tsx b/packages/website/src/components/PlaylistGenerator.tsx index f93525756..1656e22a3 100644 --- a/packages/website/src/components/PlaylistGenerator.tsx +++ b/packages/website/src/components/PlaylistGenerator.tsx @@ -1,4 +1,4 @@ -import { tankIcon } from "@blitzkit/core"; +import { fisherYates, tankIcon } from "@blitzkit/core"; import { literals } from "@blitzkit/i18n"; import { ExclamationTriangleIcon } from "@radix-ui/react-icons"; import { Box, Button, Flex, Grid, Text } from "@radix-ui/themes"; @@ -21,16 +21,10 @@ export function PlaylistGenerator() { const { strings, locale } = useLocale(); const wargaming = App.use((state) => state.logins.wargaming); const filters = TankFilters.use(); - const randomTankList = useMemo(() => { - const list = Object.values(tankDefinitions.tanks); - - for (let i = list.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * (i + 1)); - [list[i], list[j]] = [list[j], list[i]]; - } - - return list; - }, [filters]); + const randomTankList = useMemo( + () => fisherYates(Object.values(tankDefinitions.tanks)), + [filters] + ); const tanks = usePromise( () => filterTanks(filters, randomTankList, wargaming?.id), // react-promise-suspense has awful type annotations diff --git a/packages/website/src/components/PlaylistOrder.tsx b/packages/website/src/components/PlaylistOrder.tsx index d608e065c..e5e8fcec2 100644 --- a/packages/website/src/components/PlaylistOrder.tsx +++ b/packages/website/src/components/PlaylistOrder.tsx @@ -14,7 +14,6 @@ export function PlaylistOrder() { maxHeight="100%" > - diff --git a/packages/website/src/core/blitzkit/generatePlaylist.ts b/packages/website/src/core/blitzkit/generatePlaylist.ts index 717226b6c..a86510fbd 100644 --- a/packages/website/src/core/blitzkit/generatePlaylist.ts +++ b/packages/website/src/core/blitzkit/generatePlaylist.ts @@ -1,4 +1,5 @@ import { + fisherYates, getTankStats, idToRegion, type IndividualTankStats, @@ -24,14 +25,10 @@ export async function generatePlaylist() { } } - for (let i = filtered.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * (i + 1)); - [filtered[i], filtered[j]] = [filtered[j], filtered[i]]; - } + fisherYates(filtered); Playlist.mutate((draft) => { - draft.list = filtered.map((tank, index) => ({ - index, + draft.list = filtered.map((tank) => ({ tank, battles: stats[tank.id]?.all.battles, wins: stats[tank.id]?.all.wins,