From cd16d92f0ecf8daa2b8f692ac0fea57ee42b0f72 Mon Sep 17 00:00:00 2001
From: "Kalle (Sendou)" <38327916+Sendouc@users.noreply.github.com>
Date: Tue, 9 Mar 2021 11:57:42 +0200
Subject: [PATCH] xrank in app
---
.../xrank/components}/Top500Table.tsx | 0
app/xrank/components/TrendTier.tsx | 90 +++++++
.../xrank/components}/WeaponLineChart.tsx | 0
app/xrank/components/XSearchPage.tsx | 85 +++++++
app/xrank/components/XTrendsPage.tsx | 135 +++++++++++
.../getXTrends.ts => app/xrank/service.ts | 57 ++++-
pages/xsearch/[[...slug]].tsx | 104 +-------
pages/xtrends.tsx | 227 +-----------------
prisma/queries/getTop500PlacementsByMonth.ts | 41 ----
9 files changed, 379 insertions(+), 360 deletions(-)
rename {components/top500 => app/xrank/components}/Top500Table.tsx (100%)
create mode 100644 app/xrank/components/TrendTier.tsx
rename {components/top500 => app/xrank/components}/WeaponLineChart.tsx (100%)
create mode 100644 app/xrank/components/XSearchPage.tsx
create mode 100644 app/xrank/components/XTrendsPage.tsx
rename prisma/queries/getXTrends.ts => app/xrank/service.ts (52%)
delete mode 100644 prisma/queries/getTop500PlacementsByMonth.ts
diff --git a/components/top500/Top500Table.tsx b/app/xrank/components/Top500Table.tsx
similarity index 100%
rename from components/top500/Top500Table.tsx
rename to app/xrank/components/Top500Table.tsx
diff --git a/app/xrank/components/TrendTier.tsx b/app/xrank/components/TrendTier.tsx
new file mode 100644
index 000000000..32be626e3
--- /dev/null
+++ b/app/xrank/components/TrendTier.tsx
@@ -0,0 +1,90 @@
+import {
+ Box,
+ Flex,
+ Popover,
+ PopoverArrow,
+ PopoverContent,
+ PopoverTrigger,
+} from "@chakra-ui/react";
+import { useLingui } from "@lingui/react";
+import WeaponLineChart from "app/xrank/components/WeaponLineChart";
+import SubText from "components/common/SubText";
+import WeaponImage from "components/common/WeaponImage";
+import { useMyTheme } from "hooks/common";
+
+const TrendTier = ({
+ tier,
+ weapons,
+ getDataForChart,
+ mode,
+}: {
+ tier: { label: string; criteria: number; color: string };
+ weapons: {
+ name: string;
+ count: number;
+ xPowerAverage: number;
+ }[];
+ mode: string;
+ getDataForChart: (weapon: string) => { count: number }[];
+}) => {
+ const { i18n } = useLingui();
+ const { gray, secondaryBgColor } = useMyTheme();
+
+ if (!weapons.length) return null;
+
+ return (
+
+
+
+ {tier.label}
+
+
+ {tier.criteria === 0.002 ? ">0%" : `${tier.criteria}%`}
+
+
+
+ {weapons.map((weapon) => (
+
+
+
+
+
+ {weapon.count} / {weapon.xPowerAverage.toFixed(1)}
+
+
+
+
+
+
+
+ {i18n._(weapon.name)}
+ {i18n._(mode)}
+
+ getDataForChart(weapon.name)}
+ />
+
+
+
+ ))}
+
+
+ );
+};
+
+export default TrendTier;
diff --git a/components/top500/WeaponLineChart.tsx b/app/xrank/components/WeaponLineChart.tsx
similarity index 100%
rename from components/top500/WeaponLineChart.tsx
rename to app/xrank/components/WeaponLineChart.tsx
diff --git a/app/xrank/components/XSearchPage.tsx b/app/xrank/components/XSearchPage.tsx
new file mode 100644
index 000000000..3b48465ca
--- /dev/null
+++ b/app/xrank/components/XSearchPage.tsx
@@ -0,0 +1,85 @@
+import { Radio, RadioGroup, Select, Stack } from "@chakra-ui/react";
+import { t } from "@lingui/macro";
+import { RankedMode } from "@prisma/client";
+import Top500Table from "app/xrank/components/Top500Table";
+import HeaderBanner from "components/layout/HeaderBanner";
+import { useRouter } from "next/router";
+import { useEffect, useState } from "react";
+import { Top500PlacementsByMonth } from "../service";
+
+export interface XSearchPageProps {
+ placements: Top500PlacementsByMonth;
+ monthOptions: { label: string; value: string }[];
+}
+
+const XSearchPage = ({ placements, monthOptions }: XSearchPageProps) => {
+ const [variables, setVariables] = useState<{
+ month: number;
+ year: number;
+ mode: RankedMode;
+ }>({
+ month: Number(monthOptions[0].value.split(",")[0]),
+ year: Number(monthOptions[0].value.split(",")[1]),
+ mode: "SZ" as RankedMode,
+ });
+
+ const router = useRouter();
+
+ useEffect(() => {
+ router.replace(
+ `/xsearch/${variables.year}/${variables.month}/${variables.mode}`
+ );
+ }, [variables]);
+
+ //TODO: layout can be persistent between route changes
+ return (
+ <>
+
+
+ setVariables({ ...variables, mode: value as RankedMode })
+ }
+ mt={4}
+ mb={8}
+ >
+
+ {t`SZ`}
+ {t`TC`}
+ {t`RM`}
+ {t`CB`}
+
+
+
+ >
+ );
+};
+
+XSearchPage.header = (
+
+);
+
+export default XSearchPage;
diff --git a/app/xrank/components/XTrendsPage.tsx b/app/xrank/components/XTrendsPage.tsx
new file mode 100644
index 000000000..a05f6bab4
--- /dev/null
+++ b/app/xrank/components/XTrendsPage.tsx
@@ -0,0 +1,135 @@
+import { Box, Select } from "@chakra-ui/react";
+import { Trans } from "@lingui/macro";
+import ModeSelector from "components/common/ModeSelector";
+import HeaderBanner from "components/layout/HeaderBanner";
+import { useMyTheme } from "hooks/common";
+import { useXTrends } from "hooks/xtrends";
+import { XTrends } from "../service";
+import TrendTier from "./TrendTier";
+
+const tiers = [
+ {
+ label: "X",
+ criteria: 6,
+ color: "purple.700",
+ },
+ {
+ label: "S+",
+ criteria: 5,
+ color: "red.700",
+ },
+ {
+ label: "S",
+ criteria: 4,
+ color: "red.700",
+ },
+ {
+ label: "A+",
+ criteria: 3,
+ color: "orange.700",
+ },
+ {
+ label: "A",
+ criteria: 2,
+ color: "orange.700",
+ },
+ {
+ label: "B+",
+ criteria: 1.5,
+ color: "yellow.700",
+ },
+ {
+ label: "B",
+ criteria: 1,
+ color: "yellow.700",
+ },
+ {
+ label: "C+",
+ criteria: 0.4,
+ color: "green.700",
+ },
+ {
+ label: "C",
+ criteria: 0.002, //1 in 500
+ color: "green.700",
+ },
+] as const;
+
+export interface XTrendsPageProps {
+ trends: XTrends;
+}
+
+const XTrendsPage = ({ trends }: XTrendsPageProps) => {
+ const { gray } = useMyTheme();
+ const {
+ state,
+ dispatch,
+ weaponData,
+ getDataForChart,
+ monthOptions,
+ } = useXTrends(trends);
+
+ return (
+ <>
+
+
+ Here you can find X Rank Top 500 usage tier lists. For example for a
+ weapon to be in the X tier it needs at least 30 placements in that
+ mode that month. Below the weapon count and X Power average are shown.
+
+
+
+ dispatch({ type: "SET_MODE", mode })}
+ />
+ {tiers.map((tier, i) => (
+ {
+ const targetCount = 500 * (tier.criteria / 100);
+ const previousTargetCount =
+ i === 0 ? Infinity : 500 * (tiers[i - 1].criteria / 100);
+
+ return (
+ weapon.count >= targetCount && weapon.count < previousTargetCount
+ );
+ })}
+ getDataForChart={getDataForChart}
+ mode={state.mode}
+ />
+ ))}
+ >
+ );
+};
+
+XTrendsPage.header = (
+
+);
+
+export default XTrendsPage;
diff --git a/prisma/queries/getXTrends.ts b/app/xrank/service.ts
similarity index 52%
rename from prisma/queries/getXTrends.ts
rename to app/xrank/service.ts
index 6d115a45d..a454e0bea 100644
--- a/prisma/queries/getXTrends.ts
+++ b/app/xrank/service.ts
@@ -1,9 +1,9 @@
-import { Prisma } from "@prisma/client";
+import { Prisma, RankedMode } from "@prisma/client";
import prisma from "prisma/client";
-export type GetXTrendsData = Prisma.PromiseReturnType;
+export type XTrends = Prisma.PromiseReturnType;
-export const getXTrends = async () => {
+const getXTrends = async () => {
const placements = await prisma.xRankPlacement.findMany({
select: { mode: true, month: true, year: true, weapon: true, xPower: true },
});
@@ -49,3 +49,54 @@ export const getXTrends = async () => {
return result;
};
+
+export type Top500PlacementsByMonth = Prisma.PromiseReturnType<
+ typeof getTop500PlacementsByMonth
+>;
+
+const getTop500PlacementsByMonth = async ({
+ month,
+ year,
+ mode,
+}: {
+ month: number;
+ year: number;
+ mode: RankedMode;
+}) => {
+ return prisma.xRankPlacement.findMany({
+ where: { month, year, mode },
+ orderBy: { ranking: "asc" },
+ select: {
+ playerName: true,
+ xPower: true,
+ ranking: true,
+ switchAccountId: true,
+ weapon: true,
+ player: {
+ include: {
+ user: {
+ select: {
+ discordId: true,
+ discordAvatar: true,
+ discriminator: true,
+ username: true,
+ profile: { select: { customUrlPath: true } },
+ },
+ },
+ },
+ },
+ },
+ });
+};
+
+export type MostRecentResult = Prisma.PromiseReturnType<
+ typeof getMostRecentResult
+>;
+
+const getMostRecentResult = () => {
+ return prisma.xRankPlacement.findFirst({
+ orderBy: [{ year: "desc" }, { month: "desc" }],
+ });
+};
+
+export default { getXTrends, getTop500PlacementsByMonth, getMostRecentResult };
diff --git a/pages/xsearch/[[...slug]].tsx b/pages/xsearch/[[...slug]].tsx
index 6f8013319..9e4c13f59 100644
--- a/pages/xsearch/[[...slug]].tsx
+++ b/pages/xsearch/[[...slug]].tsx
@@ -1,89 +1,13 @@
-import { Radio, RadioGroup, Select, Stack } from "@chakra-ui/react";
-import { t } from "@lingui/macro";
import { RankedMode } from "@prisma/client";
-import HeaderBanner from "components/layout/HeaderBanner";
-import Top500Table from "components/top500/Top500Table";
+import XSearchPage, {
+ XSearchPageProps,
+} from "app/xrank/components/XSearchPage";
+import xRankService from "app/xrank/service";
import { GetStaticPaths, GetStaticProps } from "next";
-import { useRouter } from "next/router";
-import prisma from "prisma/client";
-import {
- getTop500PlacementsByMonth,
- GetTop500PlacementsByMonthData,
-} from "prisma/queries/getTop500PlacementsByMonth";
-import { useEffect, useState } from "react";
import { getLocalizedMonthYearString } from "utils/strings";
-interface Props {
- placements: GetTop500PlacementsByMonthData;
- monthOptions: { label: string; value: string }[];
-}
-
-const XSearchPage = ({ placements, monthOptions }: Props) => {
- const [variables, setVariables] = useState<{
- month: number;
- year: number;
- mode: RankedMode;
- }>({
- month: Number(monthOptions[0].value.split(",")[0]),
- year: Number(monthOptions[0].value.split(",")[1]),
- mode: "SZ" as RankedMode,
- });
-
- const router = useRouter();
-
- useEffect(() => {
- router.replace(
- `/xsearch/${variables.year}/${variables.month}/${variables.mode}`
- );
- }, [variables]);
-
- //TODO: layout can be persistent between route changes
- return (
- <>
-
-
- setVariables({ ...variables, mode: value as RankedMode })
- }
- mt={4}
- mb={8}
- >
-
- {t`SZ`}
- {t`TC`}
- {t`RM`}
- {t`CB`}
-
-
-
- >
- );
-};
-
export const getStaticPaths: GetStaticPaths = async () => {
- const mostRecentResult = await prisma.xRankPlacement.findFirst({
- orderBy: [{ year: "desc" }, { month: "desc" }],
- });
+ const mostRecentResult = await xRankService.getMostRecentResult();
if (!mostRecentResult) return { paths: [], fallback: false };
@@ -120,10 +44,10 @@ export const getStaticPaths: GetStaticPaths = async () => {
};
};
-export const getStaticProps: GetStaticProps = async ({ params }) => {
- const mostRecentResult = await prisma.xRankPlacement.findFirst({
- orderBy: [{ year: "desc" }, { month: "desc" }],
- });
+export const getStaticProps: GetStaticProps = async ({
+ params,
+}) => {
+ const mostRecentResult = await xRankService.getMostRecentResult();
if (!mostRecentResult) throw Error("No X Rank Placements");
@@ -138,7 +62,7 @@ export const getStaticProps: GetStaticProps = async ({ params }) => {
if (isNaN(month) || isNaN(year)) return { notFound: true };
- const placements = await getTop500PlacementsByMonth({
+ const placements = await xRankService.getTop500PlacementsByMonth({
month,
year,
mode: slug[2] as RankedMode,
@@ -185,12 +109,4 @@ export function getMonthOptions(latestMonth: number, latestYear: number) {
return monthChoices;
}
-XSearchPage.header = (
-
-);
-
export default XSearchPage;
diff --git a/pages/xtrends.tsx b/pages/xtrends.tsx
index ebc7ea85e..c6a4263cb 100644
--- a/pages/xtrends.tsx
+++ b/pages/xtrends.tsx
@@ -1,228 +1,11 @@
-import {
- Box,
- Flex,
- Popover,
- PopoverArrow,
- PopoverContent,
- PopoverTrigger,
- Select,
-} from "@chakra-ui/react";
-import { Trans } from "@lingui/macro";
-import { useLingui } from "@lingui/react";
-import ModeSelector from "components/common/ModeSelector";
-import SubText from "components/common/SubText";
-import WeaponImage from "components/common/WeaponImage";
-import HeaderBanner from "components/layout/HeaderBanner";
-import WeaponLineChart from "components/top500/WeaponLineChart";
-import { useMyTheme } from "hooks/common";
-import { useXTrends } from "hooks/xtrends";
+import { XTrendsPageProps } from "app/xrank/components/XTrendsPage";
+import xRankService from "app/xrank/service";
import { GetStaticProps } from "next";
-import { getXTrends, GetXTrendsData } from "prisma/queries/getXTrends";
-const tiers = [
- {
- label: "X",
- criteria: 6,
- color: "purple.700",
- },
- {
- label: "S+",
- criteria: 5,
- color: "red.700",
- },
- {
- label: "S",
- criteria: 4,
- color: "red.700",
- },
- {
- label: "A+",
- criteria: 3,
- color: "orange.700",
- },
- {
- label: "A",
- criteria: 2,
- color: "orange.700",
- },
- {
- label: "B+",
- criteria: 1.5,
- color: "yellow.700",
- },
- {
- label: "B",
- criteria: 1,
- color: "yellow.700",
- },
- {
- label: "C+",
- criteria: 0.4,
- color: "green.700",
- },
- {
- label: "C",
- criteria: 0.002, //1 in 500
- color: "green.700",
- },
-] as const;
+export { default as default } from "app/xrank/components/XTrendsPage";
-interface Props {
- trends: GetXTrendsData;
-}
-
-const XTrendsPage = ({ trends }: { trends: GetXTrendsData }) => {
- const { gray } = useMyTheme();
- const {
- state,
- dispatch,
- weaponData,
- getDataForChart,
- monthOptions,
- } = useXTrends(trends);
-
- return (
- <>
-
-
- Here you can find X Rank Top 500 usage tier lists. For example for a
- weapon to be in the X tier it needs at least 30 placements in that
- mode that month. Below the weapon count and X Power average are shown.
-
-
-
- dispatch({ type: "SET_MODE", mode })}
- />
- {tiers.map((tier, i) => (
- {
- const targetCount = 500 * (tier.criteria / 100);
- const previousTargetCount =
- i === 0 ? Infinity : 500 * (tiers[i - 1].criteria / 100);
-
- return (
- weapon.count >= targetCount && weapon.count < previousTargetCount
- );
- })}
- getDataForChart={getDataForChart}
- mode={state.mode}
- />
- ))}
- >
- );
-};
-
-function Tier({
- tier,
- weapons,
- getDataForChart,
- mode,
-}: {
- tier: { label: string; criteria: number; color: string };
- weapons: {
- name: string;
- count: number;
- xPowerAverage: number;
- }[];
- mode: string;
- getDataForChart: (weapon: string) => { count: number }[];
-}) {
- const { i18n } = useLingui();
- const { gray, secondaryBgColor } = useMyTheme();
-
- if (!weapons.length) return null;
-
- return (
-
-
-
- {tier.label}
-
-
- {tier.criteria === 0.002 ? ">0%" : `${tier.criteria}%`}
-
-
-
- {weapons.map((weapon) => (
-
-
-
-
-
- {weapon.count} / {weapon.xPowerAverage.toFixed(1)}
-
-
-
-
-
-
-
- {i18n._(weapon.name)}
- {i18n._(mode)}
-
- getDataForChart(weapon.name)}
- />
-
-
-
- ))}
-
-
- );
-}
-
-export const getStaticProps: GetStaticProps = async () => {
- const trends = await getXTrends();
+export const getStaticProps: GetStaticProps = async () => {
+ const trends = await xRankService.getXTrends();
return { props: { trends } };
};
-
-XTrendsPage.header = (
-
-);
-
-export default XTrendsPage;
diff --git a/prisma/queries/getTop500PlacementsByMonth.ts b/prisma/queries/getTop500PlacementsByMonth.ts
deleted file mode 100644
index 18b41044c..000000000
--- a/prisma/queries/getTop500PlacementsByMonth.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import { Prisma, RankedMode } from "@prisma/client";
-import prisma from "prisma/client";
-
-export type GetTop500PlacementsByMonthData = Prisma.PromiseReturnType<
- typeof getTop500PlacementsByMonth
->;
-
-export const getTop500PlacementsByMonth = async ({
- month,
- year,
- mode,
-}: {
- month: number;
- year: number;
- mode: RankedMode;
-}) => {
- return prisma.xRankPlacement.findMany({
- where: { month, year, mode },
- orderBy: { ranking: "asc" },
- select: {
- playerName: true,
- xPower: true,
- ranking: true,
- switchAccountId: true,
- weapon: true,
- player: {
- include: {
- user: {
- select: {
- discordId: true,
- discordAvatar: true,
- discriminator: true,
- username: true,
- profile: { select: { customUrlPath: true } },
- },
- },
- },
- },
- },
- });
-};