- {...{ game, playtype, chart, reqUser, scoreState, thisScore }}
+ {...{ game, playtype, chart, reqUser: user, scoreState, thisScore, user }}
DocComponent={props =>
GenericScoreContentDropdown({
...props,
diff --git a/client/src/components/tables/dropdowns/components/PlayHistory.tsx b/client/src/components/tables/dropdowns/components/PlayHistory.tsx
index e51bbf8f4..0a994b30a 100644
--- a/client/src/components/tables/dropdowns/components/PlayHistory.tsx
+++ b/client/src/components/tables/dropdowns/components/PlayHistory.tsx
@@ -16,14 +16,14 @@ export default function PlayHistory({
isLoading: boolean;
error: UnsuccessfulAPIFetchResponse | null;
} & GamePT) {
- if (isLoading || !data) {
- return ;
- }
-
if (error) {
return <>{error.description}>;
}
+ if (isLoading || !data) {
+ return ;
+ }
+
return (
diff --git a/client/src/components/tables/history-scores/HistoryScoreTable.tsx b/client/src/components/tables/history-scores/HistoryScoreTable.tsx
index dde2351a1..60ad474c5 100644
--- a/client/src/components/tables/history-scores/HistoryScoreTable.tsx
+++ b/client/src/components/tables/history-scores/HistoryScoreTable.tsx
@@ -77,7 +77,7 @@ function Row({
game: Game;
}) {
return (
-
+
diff --git a/client/src/components/tables/pbs/BMSPBTable.tsx b/client/src/components/tables/pbs/BMSPBTable.tsx
index 813c7e28f..a70c5676a 100644
--- a/client/src/components/tables/pbs/BMSPBTable.tsx
+++ b/client/src/components/tables/pbs/BMSPBTable.tsx
@@ -143,7 +143,6 @@ function Row({
scoreState={scoreState}
/>
}
- className={scoreState.highlight ? "highlighted-row" : ""}
>
{indexCol && }
diff --git a/client/src/components/tables/pbs/GenericPBTable.tsx b/client/src/components/tables/pbs/GenericPBTable.tsx
index a9cae2516..ec4f9bb8b 100644
--- a/client/src/components/tables/pbs/GenericPBTable.tsx
+++ b/client/src/components/tables/pbs/GenericPBTable.tsx
@@ -109,7 +109,7 @@ function Row({
scoreState={scoreState}
/>
}
- className={scoreState.highlight ? "highlighted-row" : ""}
+
>
{indexCol && }
diff --git a/client/src/components/tables/pbs/MusecaPBTable.tsx b/client/src/components/tables/pbs/MusecaPBTable.tsx
index 0e7fb6af9..f7683ecd6 100644
--- a/client/src/components/tables/pbs/MusecaPBTable.tsx
+++ b/client/src/components/tables/pbs/MusecaPBTable.tsx
@@ -97,7 +97,6 @@ function Row({
scoreState={scoreState}
/>
}
- className={scoreState.highlight ? "highlighted-row" : ""}
>
{indexCol && }
diff --git a/client/src/components/tables/pbs/SDVXPBTable.tsx b/client/src/components/tables/pbs/SDVXPBTable.tsx
index aad0faa92..64b2f7ac0 100644
--- a/client/src/components/tables/pbs/SDVXPBTable.tsx
+++ b/client/src/components/tables/pbs/SDVXPBTable.tsx
@@ -96,7 +96,7 @@ function Row({
scoreState={scoreState}
/>
}
- className={scoreState.highlight ? "highlighted-row" : ""}
+
>
{indexCol && }
diff --git a/client/src/components/tables/scores/BMSScoreTable.tsx b/client/src/components/tables/scores/BMSScoreTable.tsx
index eae13e668..a9edfe03e 100644
--- a/client/src/components/tables/scores/BMSScoreTable.tsx
+++ b/client/src/components/tables/scores/BMSScoreTable.tsx
@@ -8,6 +8,7 @@ import BMSDifficultyCell from "../cells/BMSDifficultyCell";
import IndicatorsCell from "../cells/IndicatorsCell";
import TimestampCell from "../cells/TimestampCell";
import TitleCell from "../cells/TitleCell";
+import UserCell from "../cells/UserCell";
import DropdownRow from "../components/DropdownRow";
import TachiTable, { Header } from "../components/TachiTable";
import { useScoreState } from "../components/UseScoreState";
@@ -16,46 +17,50 @@ import BMSScoreCoreCells from "../game-core-cells/BMSScoreCoreCells";
import IndicatorHeader from "../headers/IndicatorHeader";
export default function BMSScoreTable({
- reqUser,
dataset,
pageLen,
playtype,
+ userCol = false,
}: {
- reqUser: PublicUserDocument;
dataset: ScoreDataset<"bms:7K" | "bms:14K">;
pageLen?: integer;
playtype: Playtypes["bms"];
+ userCol?: boolean;
}) {
+ const headers: Header[0]>[] = [
+ [
+ "Chart",
+ "Chart",
+ NumericSOV(
+ x =>
+ x.__related.chart.tierlistInfo["sgl-EC"]?.value ??
+ x.__related.chart.tierlistInfo["sgl-HC"]?.value ??
+ x.__related.chart.levelNum
+ ),
+ ],
+ IndicatorHeader,
+ ["Song", "Song", StrSOV(x => x.__related.song.title)],
+ ["Score", "Score", NumericSOV(x => x.scoreData.percent)],
+ ["Deltas", "Deltas", NumericSOV(x => x.scoreData.percent)],
+ ["Lamp", "Lamp", NumericSOV(x => x.scoreData.lampIndex)],
+ ["Sieglinde", "sgl.", NumericSOV(x => x.calculatedData.sieglinde ?? 0)],
+
+ ["Timestamp", "Timestamp", NumericSOV(x => x.timeAchieved ?? 0)],
+ ];
+
+ if (userCol) {
+ headers.unshift(["User", "User", StrSOV(x => x.__related.user.username)]);
+ }
+
return (
- x.__related.chart.tierlistInfo["sgl-EC"]?.value ??
- x.__related.chart.tierlistInfo["sgl-HC"]?.value ??
- x.__related.chart.levelNum
- ),
- ],
- IndicatorHeader,
- ["Song", "Song", StrSOV(x => x.__related.song.title)],
- ["Score", "Score", NumericSOV(x => x.scoreData.percent)],
- ["Deltas", "Deltas", NumericSOV(x => x.scoreData.percent)],
- ["Lamp", "Lamp", NumericSOV(x => x.scoreData.lampIndex)],
- ["Sieglinde", "sgl.", NumericSOV(x => x.calculatedData.sieglinde ?? 0)],
-
- ["Timestamp", "Timestamp", NumericSOV(x => x.timeAchieved ?? 0)],
- ] as Header[0]>[]
- }
+ headers={headers}
entryName="Scores"
searchFunctions={CreateDefaultScoreSearchParams("bms", playtype)}
rowFunction={sc => (
-
+
)}
/>
);
@@ -63,22 +68,21 @@ export default function BMSScoreTable({
function Row({
sc,
- reqUser,
playtype,
+ userCol,
}: {
sc: ScoreDataset<"bms:7K" | "bms:14K">[0];
- reqUser: PublicUserDocument;
playtype: Playtype;
+ userCol: boolean;
}) {
const scoreState = useScoreState(sc);
return (
}
>
+ {userCol && }
[] = [
+ ["Chart", "Chart", NumericSOV(x => x.__related.chart.levelNum)],
+ IndicatorHeader,
+ ["Song", "Song", StrSOV(x => x.__related.song.title)],
+ ["Score", "Score", NumericSOV(x => x.scoreData.percent)],
+ ["Lamp", "Lamp", NumericSOV(x => x.scoreData.lampIndex)],
+ [
+ gptConfig.defaultScoreRatingAlg,
+ gptConfig.defaultScoreRatingAlg,
+ NumericSOV(x => x.calculatedData[gptConfig.defaultScoreRatingAlg] ?? 0),
+ ],
+ ["Timestamp", "Timestamp", NumericSOV(x => x.timeAchieved ?? 0)],
+ ];
+
+ if (userCol) {
+ headers.unshift(["User", "User", StrSOV(x => x.__related.user.username)]);
+ }
+
return (
x.__related.chart.levelNum)],
- IndicatorHeader,
- ["Song", "Song", StrSOV(x => x.__related.song.title)],
- ["Score", "Score", NumericSOV(x => x.scoreData.percent)],
- ["Lamp", "Lamp", NumericSOV(x => x.scoreData.lampIndex)],
- [
- gptConfig.defaultScoreRatingAlg,
- gptConfig.defaultScoreRatingAlg,
- NumericSOV(x => x.calculatedData[gptConfig.defaultScoreRatingAlg] ?? 0),
- ],
- ["Timestamp", "Timestamp", NumericSOV(x => x.timeAchieved ?? 0)],
- ]}
+ headers={headers}
entryName="Scores"
searchFunctions={CreateDefaultScoreSearchParams(game, playtype)}
rowFunction={sc => (
-
+
)}
/>
);
@@ -61,20 +76,22 @@ function Row({
sc,
reqUser,
showScore,
+ userCol,
}: {
sc: ScoreDataset[0];
reqUser: PublicUserDocument;
showScore?: boolean;
+ userCol: boolean;
}) {
const scoreState = useScoreState(sc);
return (
}
>
+ {userCol && }
diff --git a/client/src/components/tables/scores/IIDXScoreTable.tsx b/client/src/components/tables/scores/IIDXScoreTable.tsx
index e36aee557..31da73b23 100644
--- a/client/src/components/tables/scores/IIDXScoreTable.tsx
+++ b/client/src/components/tables/scores/IIDXScoreTable.tsx
@@ -10,6 +10,7 @@ import DifficultyCell from "../cells/DifficultyCell";
import IndicatorsCell from "../cells/IndicatorsCell";
import TimestampCell from "../cells/TimestampCell";
import TitleCell from "../cells/TitleCell";
+import UserCell from "../cells/UserCell";
import DropdownRow from "../components/DropdownRow";
import SelectableRating from "../components/SelectableRating";
import TachiTable, { Header, ZTableTHProps } from "../components/TachiTable";
@@ -19,60 +20,64 @@ import IIDXScoreCoreCells from "../game-core-cells/IIDXScoreCoreCells";
import IndicatorHeader from "../headers/IndicatorHeader";
export default function IIDXScoreTable({
- reqUser,
dataset,
pageLen,
playtype,
+ userCol = false,
}: {
- reqUser: PublicUserDocument;
dataset: ScoreDataset<"iidx:SP" | "iidx:DP">;
pageLen?: integer;
playtype: Playtypes["iidx"];
+ userCol?: boolean;
}) {
const defaultRating = useScoreRatingAlg<"iidx:SP" | "iidx:DP">("iidx", playtype);
const [rating, setRating] = useState(
defaultRating
);
+ const headers: Header[0]>[] = [
+ [
+ "Chart",
+ "Chart",
+ NumericSOV(
+ x =>
+ x.__related.chart.tierlistInfo["kt-NC"]?.value ??
+ x.__related.chart.tierlistInfo["kt-HC"]?.value ??
+ x.__related.chart.levelNum
+ ),
+ ],
+ IndicatorHeader,
+ ["Song", "Song", StrSOV(x => x.__related.song.title)],
+ ["Score", "Score", NumericSOV(x => x.scoreData.percent)],
+ ["Deltas", "Deltas", NumericSOV(x => x.scoreData.percent)],
+ ["Lamp", "Lamp", NumericSOV(x => x.scoreData.lampIndex)],
+ [
+ "Rating",
+ "Rating",
+ NumericSOV(x => x.calculatedData[rating] ?? 0),
+ (thProps: ZTableTHProps) => (
+
+ key={nanoid()}
+ game="iidx"
+ playtype={playtype}
+ rating={rating}
+ setRating={setRating}
+ {...thProps}
+ />
+ ),
+ ],
+ ["Timestamp", "Timestamp", NumericSOV(x => x.timeAchieved ?? 0)],
+ ];
+
+ if (userCol) {
+ headers.unshift(["User", "User", StrSOV(x => x.__related.user.username)]);
+ }
+
return (
- x.__related.chart.tierlistInfo["kt-NC"]?.value ??
- x.__related.chart.tierlistInfo["kt-HC"]?.value ??
- x.__related.chart.levelNum
- ),
- ],
- IndicatorHeader,
- ["Song", "Song", StrSOV(x => x.__related.song.title)],
- ["Score", "Score", NumericSOV(x => x.scoreData.percent)],
- ["Deltas", "Deltas", NumericSOV(x => x.scoreData.percent)],
- ["Lamp", "Lamp", NumericSOV(x => x.scoreData.lampIndex)],
- [
- "Rating",
- "Rating",
- NumericSOV(x => x.calculatedData[rating] ?? 0),
- (thProps: ZTableTHProps) => (
-
- key={nanoid()}
- game="iidx"
- playtype={playtype}
- rating={rating}
- setRating={setRating}
- {...thProps}
- />
- ),
- ],
- ["Timestamp", "Timestamp", NumericSOV(x => x.timeAchieved ?? 0)],
- ] as Header[0]>[]
- }
+ headers={headers}
entryName="Scores"
searchFunctions={CreateDefaultScoreSearchParams("iidx", playtype)}
rowFunction={sc => (
@@ -80,8 +85,8 @@ export default function IIDXScoreTable({
key={sc.scoreID}
playtype={playtype}
sc={sc}
- reqUser={reqUser}
rating={rating}
+ userCol={userCol}
/>
)}
/>
@@ -90,31 +95,32 @@ export default function IIDXScoreTable({
function Row({
sc,
- reqUser,
rating,
playtype,
+ userCol,
}: {
sc: ScoreDataset<"iidx:SP" | "iidx:DP">[0];
- reqUser: PublicUserDocument;
rating: ScoreCalculatedDataLookup["iidx:SP" | "iidx:DP"];
playtype: Playtype;
+ userCol: boolean;
}) {
const scoreState = useScoreState(sc);
return (
}
>
+ {userCol && }
;
pageLen?: integer;
playtype: Playtypes["museca"];
+ userCol: boolean;
}) {
+ const headers: Header[0]>[] = [
+ ["Chart", "Chart", NumericSOV(x => x.__related.chart.levelNum)],
+ IndicatorHeader,
+ ["Song", "Song", StrSOV(x => x.__related.song.title)],
+ ["Score", "Score", NumericSOV(x => x.scoreData.percent)],
+ ["Near-Miss", "Nr. Ms.", NumericSOV(x => x.scoreData.percent)],
+ ["Lamp", "Lamp", NumericSOV(x => x.scoreData.lampIndex)],
+ ["KtRating", "KtRating", NumericSOV(x => x.calculatedData.ktRating ?? 0)],
+
+ ["Timestamp", "Timestamp", NumericSOV(x => x.timeAchieved ?? 0)],
+ ];
+
+ if (userCol) {
+ headers.unshift(["User", "User", StrSOV(x => x.__related.user.username)]);
+ }
+
return (
x.__related.chart.levelNum)],
- IndicatorHeader,
- ["Song", "Song", StrSOV(x => x.__related.song.title)],
- ["Score", "Score", NumericSOV(x => x.scoreData.percent)],
- ["Near-Miss", "Nr. Ms.", NumericSOV(x => x.scoreData.percent)],
- ["Lamp", "Lamp", NumericSOV(x => x.scoreData.lampIndex)],
- ["KtRating", "KtRating", NumericSOV(x => x.calculatedData.ktRating ?? 0)],
-
- ["Timestamp", "Timestamp", NumericSOV(x => x.timeAchieved ?? 0)],
- ] as Header[0]>[]
- }
+ headers={headers}
entryName="Scores"
searchFunctions={CreateDefaultScoreSearchParams("museca", "Single")}
- rowFunction={sc =>
}
+ rowFunction={sc =>
}
/>
);
}
@@ -51,19 +58,21 @@ export default function MusecaScoreTable({
function Row({
sc,
reqUser,
+ userCol,
}: {
sc: ScoreDataset<"museca:Single">[0];
reqUser: PublicUserDocument;
+ userCol: boolean;
}) {
const scoreState = useScoreState(sc);
return (
}
>
+ {userCol && }
;
pageLen?: integer;
playtype: Playtypes["sdvx"];
+ userCol?: boolean;
}) {
+ const headers: Header[0]>[] = [
+ ["Chart", "Chart", NumericSOV(x => x.__related.chart.levelNum)],
+ IndicatorHeader,
+ ["Song", "Song", StrSOV(x => x.__related.song.title)],
+ ["Score", "Score", NumericSOV(x => x.scoreData.percent)],
+ ["Near - Miss", "Nr. Ms.", NumericSOV(x => x.scoreData.percent)],
+ ["Lamp", "Lamp", NumericSOV(x => x.scoreData.lampIndex)],
+ ["VF6", "VF6", NumericSOV(x => x.calculatedData.VF6 ?? 0)],
+
+ ["Timestamp", "Timestamp", NumericSOV(x => x.timeAchieved ?? 0)],
+ ];
+
+ if (userCol) {
+ headers.unshift(["User", "User", StrSOV(x => x.__related.user.username)]);
+ }
+
return (
x.__related.chart.levelNum)],
- IndicatorHeader,
- ["Song", "Song", StrSOV(x => x.__related.song.title)],
- ["Score", "Score", NumericSOV(x => x.scoreData.percent)],
- ["Near - Miss", "Nr. Ms.", NumericSOV(x => x.scoreData.percent)],
- ["Lamp", "Lamp", NumericSOV(x => x.scoreData.lampIndex)],
- ["VF6", "VF6", NumericSOV(x => x.calculatedData.VF6 ?? 0)],
-
- ["Timestamp", "Timestamp", NumericSOV(x => x.timeAchieved ?? 0)],
- ] as Header[0]>[]
- }
+ headers={headers}
entryName="Scores"
searchFunctions={CreateDefaultScoreSearchParams("museca", "Single")}
- rowFunction={sc =>
}
+ rowFunction={sc =>
}
/>
);
}
-function Row({ sc, reqUser }: { sc: ScoreDataset<"sdvx:Single">[0]; reqUser: PublicUserDocument }) {
+function Row({
+ sc,
+ reqUser,
+ userCol,
+}: {
+ sc: ScoreDataset<"sdvx:Single">[0];
+ reqUser: PublicUserDocument;
+ userCol: boolean;
+}) {
const scoreState = useScoreState(sc);
return (
[0]; reqUser: Pub
/>
}
>
+ {userCol && }
;
} else if (game === "bms") {
diff --git a/client/src/components/user/UGPTStatContainer.tsx b/client/src/components/user/UGPTStatContainer.tsx
index c492a26af..4f2b57584 100644
--- a/client/src/components/user/UGPTStatContainer.tsx
+++ b/client/src/components/user/UGPTStatContainer.tsx
@@ -62,14 +62,14 @@ export default function UGPTStatContainer({
}
);
- if (isLoading || !data) {
- return ;
- }
-
if (error) {
return <>{(error as any).description}>;
}
+ if (isLoading || !data) {
+ return ;
+ }
+
return (
;
}
diff --git a/client/src/components/util/LoadingWrapper.tsx b/client/src/components/util/LoadingWrapper.tsx
index 585c7194e..95e033795 100644
--- a/client/src/components/util/LoadingWrapper.tsx
+++ b/client/src/components/util/LoadingWrapper.tsx
@@ -15,13 +15,13 @@ export default function LoadingWrapper({
children: JSX.Element | JSX.Element[];
style?: CSSProperties;
}) {
- if (isLoading || !dataset) {
- return ;
- }
-
if (error) {
return An error has occured. {error.description}
;
}
+ if (isLoading || !dataset) {
+ return ;
+ }
+
return <>{children}>;
}
diff --git a/client/src/components/util/table/useZTable.tsx b/client/src/components/util/table/useZTable.tsx
index 1185c7f5e..e42531922 100644
--- a/client/src/components/util/table/useZTable.tsx
+++ b/client/src/components/util/table/useZTable.tsx
@@ -58,6 +58,7 @@ export function useZTable(originalDataset: D[], providedOptions?: Partial {
charts: ChartDocument[];
pbs: PBScoreDocument[];
}
+
+export interface GPTStatsReturn {
+ config: GamePTConfig;
+ playerCount: integer;
+ chartCount: integer;
+ scoreCount: integer;
+}
+
+export interface RecentClassesReturn {
+ classes: ClassAchievementDocument[];
+ users: PublicUserDocument[];
+}
diff --git a/client/src/types/tables.ts b/client/src/types/tables.ts
index 76ce255c6..32d5e4c64 100644
--- a/client/src/types/tables.ts
+++ b/client/src/types/tables.ts
@@ -6,6 +6,7 @@ import {
IDStringToGame,
integer,
ScoreDocument,
+ PublicUserDocument,
} from "tachi-common";
export type PBDataset = (PBScoreDocument & {
@@ -14,12 +15,18 @@ export type PBDataset = (PBScoreDocument & {
})[];
export type ScoreDataset = (ScoreDocument & {
- __related: { chart: ChartDocument; song: SongDocument; index: integer };
+ __related: {
+ chart: ChartDocument;
+ song: SongDocument;
+ index: integer;
+ user: PublicUserDocument;
+ };
})[];
export type FolderDataset = (ChartDocument & {
__related: {
pb: PBScoreDocument | null;
song: SongDocument;
+ user: PublicUserDocument;
};
})[];
diff --git a/client/src/util/data.ts b/client/src/util/data.ts
index e84009a01..e5cf5e742 100644
--- a/client/src/util/data.ts
+++ b/client/src/util/data.ts
@@ -6,6 +6,7 @@ import {
SessionScoreInfo,
SongDocument,
ScoreDocument,
+ PublicUserDocument,
} from "tachi-common";
export function GetPBs(scoreInfo: SessionScoreInfo[]) {
@@ -22,6 +23,16 @@ export function CreateSongMap(songs: SongDocument[]) {
return songMap;
}
+export function CreateUserMap(users: PublicUserDocument[]) {
+ const userMap = new Map();
+
+ for (const user of users) {
+ userMap.set(user.id, user);
+ }
+
+ return userMap;
+}
+
export function CreateChartIDMap(arr: T[]): Map {
const map = new Map();
diff --git a/client/src/util/splashes.ts b/client/src/util/splashes.ts
index 8dd299243..2ec171820 100644
--- a/client/src/util/splashes.ts
+++ b/client/src/util/splashes.ts
@@ -1,3 +1,5 @@
+import { IDStrings } from "tachi-common";
+
export const neutralSplashes = ["A Rhythm Game Score Manager", "The Rhythm Game Score Manager"];
export const loggedInSplashes = [
@@ -67,6 +69,8 @@ export const loggedInSplashes = [
"~𝒕𝒉𝒆 𝒈𝒆𝒂𝒓𝒔 𝒕𝒖𝒓𝒏 𝒐𝒏𝒄𝒆 𝒎𝒐𝒓𝒆~",
"",
"come on down",
+ "The preparation for a dive is always a tense time.",
+ "Music Is Math",
];
// Stuff that's bad for the kids, you know?