diff --git a/client/src/app/pages/dashboard/users/games/_game/_playtype/folders/SpecificFolderPage.tsx b/client/src/app/pages/dashboard/users/games/_game/_playtype/folders/SpecificFolderPage.tsx index 816d49025..aab3a3680 100644 --- a/client/src/app/pages/dashboard/users/games/_game/_playtype/folders/SpecificFolderPage.tsx +++ b/client/src/app/pages/dashboard/users/games/_game/_playtype/folders/SpecificFolderPage.tsx @@ -22,7 +22,7 @@ import ReferToUser from "components/util/ReferToUser"; import SelectLinkButton from "components/util/SelectLinkButton"; import useApiQuery from "components/util/query/useApiQuery"; import useUGPTBase from "components/util/useUGPTBase"; -import { GPT_CLIENT_IMPLEMENTATIONS } from "lib/game-implementations"; +import { GetEnumColour, GPT_CLIENT_IMPLEMENTATIONS } from "lib/game-implementations"; import { GPTRatingSystem } from "lib/types"; import React, { useContext, useEffect, useMemo, useState } from "react"; import { Col, Form, Row } from "react-bootstrap"; @@ -40,6 +40,7 @@ import { SongDocument, UserDocument, integer, + GetGPTString, } from "tachi-common"; import { ConfEnumScoreMetric } from "tachi-common/types/metrics"; import { UGPTFolderReturns } from "types/api-returns"; @@ -425,6 +426,8 @@ function TierlistBreakdown({ game, folderDataset, playtype, reqUser }: InfoProps const gptImpl = GPT_CLIENT_IMPLEMENTATIONS[`${game}:${playtype}` as GPTString]; const [tierlist, setTierlist] = useState(gptImpl.ratingSystems[0].name); + const [useFancyColour, setUseFancyColour] = useState(false); + const [forceGridView, setForceGridView] = useState(false); const playerStats = useMemo( () => FolderDatasetAchievedStatus(folderDataset, game, playtype, tierlist), @@ -464,6 +467,30 @@ function TierlistBreakdown({ game, folderDataset, playtype, reqUser }: InfoProps )} + { + setUseFancyColour((e) => !e); + }} + label="Use simple clear/fail colours" + /> + + + If enabled, this will show green when you've achieved the tierlist + requirements, and red if you haven't, instead of fancier colours. + + + { + setForceGridView((e) => !e); + }} + label="Force desktop grid view" + /> + @@ -486,6 +515,8 @@ function TierlistInfoLadder({ reqUser, folderDataset, tierlistImpl, + useFancyColour, + forceGridView, }: { playerStats: Record; game: Game; @@ -493,6 +524,8 @@ function TierlistInfoLadder({ reqUser: UserDocument; tierlistImpl: GPTRatingSystem; folderDataset: FolderDataset; + useFancyColour: boolean; + forceGridView: boolean; }) { const buckets: TierlistInfo[][] = useMemo(() => { const buckets: TierlistInfo[][] = []; @@ -569,7 +602,17 @@ function TierlistInfoLadder({ ) - + ))} @@ -579,18 +622,25 @@ function TierlistInfoLadder({ function TierlistBucket({ bucket, game, + playtype, reqUser, + useFancyColour, + forceGridView, + tierlistImpl, }: { game: Game; playtype: Playtype; reqUser: UserDocument; bucket: TierlistInfo[]; + useFancyColour: boolean; + forceGridView: boolean; + tierlistImpl: GPTRatingSystem; }) { const { breakpoint: { isLg }, } = useContext(WindowContext); // xs view is tabular - if (!isLg) { + if (!isLg && !forceGridView) { return ( {bucket.map((tierlistInfo, i) => ( @@ -598,9 +648,13 @@ function TierlistBucket({ tierlistInfo={tierlistInfo} key={`${tierlistInfo.chart.chartID}-${tierlistInfo.text}`} game={game} + playtype={playtype} bucket={bucket} i={i} reqUser={reqUser} + useFancyColour={useFancyColour} + tierlistImpl={tierlistImpl} + forceGridView={forceGridView} /> ))} @@ -614,9 +668,13 @@ function TierlistBucket({ tierlistInfo={tierlistInfo} key={`${tierlistInfo.chart.chartID}-${tierlistInfo.text}`} game={game} + playtype={playtype} bucket={bucket} i={i} reqUser={reqUser} + useFancyColour={useFancyColour} + forceGridView={forceGridView} + tierlistImpl={tierlistImpl} /> ))} @@ -626,13 +684,21 @@ function TierlistBucket({ function TierlistInfoBucketValues({ tierlistInfo, game, + playtype, reqUser, + useFancyColour, + forceGridView, + tierlistImpl, }: { tierlistInfo: TierlistInfo; bucket: TierlistInfo[]; game: Game; + playtype: Playtype; i: integer; reqUser: UserDocument; + useFancyColour: boolean; + forceGridView: boolean; + tierlistImpl: GPTRatingSystem; }) { const { breakpoint } = useContext(WindowContext); @@ -643,10 +709,26 @@ function TierlistInfoBucketValues({ [AchievedStatuses.SCORE_BASED]: "bg-transparent", }; + let colourClass: string | undefined; + let colourCss: string | undefined; + + if (useFancyColour) { + const gptImpl = GPT_CLIENT_IMPLEMENTATIONS[GetGPTString(game, playtype)]; + + // @ts-expect-error lol + colourCss = gptImpl.enumColours[tierlistImpl.enumName][tierlistInfo.score]; + } else { + colourClass = statusClasses[tierlistInfo.status]; + } + + if (tierlistInfo.status === AchievedStatuses.NOT_PLAYED) { + colourClass = "bg-body-tertiary"; + } + const data = tierlistInfo.chart; // xs view - if (!breakpoint.isLg) { + if (!breakpoint.isLg && !forceGridView) { return ( @@ -664,7 +746,7 @@ function TierlistInfoBucketValues({ )} - + ); } @@ -682,7 +764,10 @@ function TierlistInfoBucketValues({ ) : undefined } > -
+
{data.__related.song.title} {" "} @@ -714,28 +799,35 @@ function TierlistInfoBucketValues({ ); } -function TierlistInfoCell({ tierlistInfo }: { tierlistInfo: TierlistInfo }) { - let colour; - const text = tierlistInfo.score ?? "NOT PLAYED"; +function TierlistInfoCell({ + tierlistInfo, + colourCss, +}: { + tierlistInfo: TierlistInfo; + colourCss: string | undefined; +}) { + let colour = colourCss; - if (tierlistInfo.status === AchievedStatuses.FAILED) { - colour = COLOUR_SET.red; - } else if (tierlistInfo.status === AchievedStatuses.NOT_PLAYED) { - colour = COLOUR_SET.red; - } else { - colour = COLOUR_SET.green; + if (!colour) { + if (tierlistInfo.status === AchievedStatuses.FAILED) { + colour = COLOUR_SET.red; + } else if (tierlistInfo.status === AchievedStatuses.NOT_PLAYED) { + colour = COLOUR_SET.red; + } else { + colour = COLOUR_SET.green; + } } return ( - {text} + {tierlistInfo.score ?? "NOT PLAYED"} ); } diff --git a/client/src/lib/game-implementations.tsx b/client/src/lib/game-implementations.tsx index e3fb66b33..900b230af 100644 --- a/client/src/lib/game-implementations.tsx +++ b/client/src/lib/game-implementations.tsx @@ -672,21 +672,7 @@ export const GPT_CLIENT_IMPLEMENTATIONS: GPTClientImplementations = { // this game has dynamic difficulties. Formatting is handled elsewhere. }, classColours: {}, - ratingSystems: [ - CreateRatingSys( - "BPM", - "How fast are the streams in this chart?", - (c) => c.data.streamBPM, - (c) => c.data.streamBPM?.toString(), - () => undefined, - (s) => [ - s.scoreData.lamp === "FAILED" - ? `Failed ${s.scoreData.survivedPercent.toFixed(2)}%` - : s.scoreData.lamp, - s.scoreData.lamp !== "FAILED", - ] - ), - ], + ratingSystems: [], scoreHeaders: [ ["Score", "Score", NumericSOV((x) => x.scoreData.finalPercent)], ["Judgements", "Hits", NumericSOV((x) => x.scoreData.scorePercent)], diff --git a/client/src/lib/games/_util.ts b/client/src/lib/games/_util.ts index c95b2e89a..12114fae1 100644 --- a/client/src/lib/games/_util.ts +++ b/client/src/lib/games/_util.ts @@ -5,6 +5,7 @@ import { GPTString } from "tachi-common"; export function CreateRatingSys( name: string, description: string, + enumName: string, toNumber: GPTRatingSystem["toNumber"], toString: GPTRatingSystem["toString"], idvDifference: GPTRatingSystem["idvDifference"] = () => false, @@ -12,6 +13,7 @@ export function CreateRatingSys( ): GPTRatingSystem { return { description, + enumName, name, toNumber, toString, diff --git a/client/src/lib/games/iidx.tsx b/client/src/lib/games/iidx.tsx index 5f9b086b8..8b3010d91 100644 --- a/client/src/lib/games/iidx.tsx +++ b/client/src/lib/games/iidx.tsx @@ -139,6 +139,7 @@ export const IIDX_SP_IMPL: GPTClientImplementation<"iidx:SP"> = { CreateRatingSys( "NC Tier", "Tierlist Ratings for Normal Clears.", + "lamp", (c) => c.data.ncTier?.value, (c) => c.data.ncTier?.text, (c) => c.data.ncTier?.individualDifference, @@ -147,6 +148,7 @@ export const IIDX_SP_IMPL: GPTClientImplementation<"iidx:SP"> = { CreateRatingSys( "HC Tier", "Tierlist Ratings for Hard Clears.", + "lamp", (c) => c.data.hcTier?.value, (c) => c.data.hcTier?.text, (c) => c.data.hcTier?.individualDifference, @@ -155,6 +157,7 @@ export const IIDX_SP_IMPL: GPTClientImplementation<"iidx:SP"> = { CreateRatingSys( "EXHC Tier", "Tierlist Ratings for EX-HARD Clears.", + "lamp", (c) => c.data.exhcTier?.value, (c) => c.data.exhcTier?.text, (c) => c.data.exhcTier?.individualDifference, diff --git a/client/src/lib/games/sdvx-usc.tsx b/client/src/lib/games/sdvx-usc.tsx index 8ad0d0077..6bf627058 100644 --- a/client/src/lib/games/sdvx-usc.tsx +++ b/client/src/lib/games/sdvx-usc.tsx @@ -154,6 +154,7 @@ export const SDVX_IMPL: GPTClientImplementation<"sdvx:Single"> = { CreateRatingSys( "Tierlist", "The unofficial SDVX clearing tierlist", + "lamp", (c) => c.data.clearTier?.value, (c) => c.data.clearTier?.text, (c) => c.data.clearTier?.individualDifference, diff --git a/client/src/lib/types.ts b/client/src/lib/types.ts index 20108346d..5820e211e 100644 --- a/client/src/lib/types.ts +++ b/client/src/lib/types.ts @@ -33,6 +33,8 @@ export type GPTDifficultyColours = Record = { name: string; description: string; + enumName: string; + toNumber: (c: ChartDocument) => number | null | undefined; toString: (c: ChartDocument) => string | null | undefined;