diff --git a/client/src/app/pages/dashboard/games/_game/_playtype/GPTLeaderboardsPage.tsx b/client/src/app/pages/dashboard/games/_game/_playtype/GPTLeaderboardsPage.tsx
index 6e5786917..4e3b3c4be 100644
--- a/client/src/app/pages/dashboard/games/_game/_playtype/GPTLeaderboardsPage.tsx
+++ b/client/src/app/pages/dashboard/games/_game/_playtype/GPTLeaderboardsPage.tsx
@@ -236,6 +236,7 @@ function ScoreLeaderboard({ game, playtype }: GamePT) {
showChart
indexCol
alg={alg}
+ defaultRankingViewMode="both-if-self"
/>
>
);
diff --git a/client/src/app/pages/dashboard/users/games/_game/_playtype/ScoresPage.tsx b/client/src/app/pages/dashboard/users/games/_game/_playtype/ScoresPage.tsx
index 8fa9a5934..e66731f44 100644
--- a/client/src/app/pages/dashboard/users/games/_game/_playtype/ScoresPage.tsx
+++ b/client/src/app/pages/dashboard/users/games/_game/_playtype/ScoresPage.tsx
@@ -27,6 +27,7 @@ import {
UnsuccessfulAPIResponse,
} from "tachi-common";
import { GamePT, SetState } from "types/react";
+import usePreferredRanking from "components/util/usePreferredRanking";
export default function ScoresPage({
reqUser,
@@ -177,6 +178,8 @@ function PBsOverview({
const { data, error } = useFetchPBs(url, reqUser);
+ const preferredRanking = usePreferredRanking();
+
return (
@@ -195,7 +198,8 @@ function PBsOverview({
showPlaycount={showPlaycount}
indexCol={indexCol}
alg={alg}
- playtype={playtype as "SP" | "DP"}
+ playtype={playtype}
+ defaultRankingViewMode={preferredRanking}
/>
) : (
diff --git a/client/src/app/pages/dashboard/users/games/_game/_playtype/UGPTSettingsPage.tsx b/client/src/app/pages/dashboard/users/games/_game/_playtype/UGPTSettingsPage.tsx
index cc917275b..3c29a2b5e 100644
--- a/client/src/app/pages/dashboard/users/games/_game/_playtype/UGPTSettingsPage.tsx
+++ b/client/src/app/pages/dashboard/users/games/_game/_playtype/UGPTSettingsPage.tsx
@@ -104,6 +104,7 @@ function PreferencesForm({ reqUser, game, playtype }: Props) {
gameSpecific: settings!.preferences.gameSpecific as any,
defaultTable: settings!.preferences.defaultTable,
scoreBucket: settings!.preferences.scoreBucket ?? gptConfig.scoreBucket,
+ preferredRanking: settings!.preferences.preferredRanking ?? "global",
},
onSubmit: async (values) => {
const rj = await APIFetchV1
(
@@ -221,6 +222,21 @@ function PreferencesForm({ reqUser, game, playtype }: Props) {
breakdown. You can still view all the same stats!
+
+ Preferred Ranking
+
+
+
+
+
+ What should {TachiConfig.name} default to when showing your score rankings?
+
+
Preferred Table
({
}) {
const defaultRating = useScoreRatingAlg(game, playtype);
- const { settings } = useLUGPTSettings();
+ const preferredRanking = usePreferredRanking();
const [rating, setRating] = useState(defaultRating);
- const [rankingViewMode, setRankingViewMode] = useState("global");
+ const [rankingViewMode, setRankingViewMode] = useState(
+ preferredRanking ?? "global"
+ );
const headers: Header[] = [
ChartHeader(game, (k) => k),
diff --git a/client/src/components/tables/pbs/PBTable.tsx b/client/src/components/tables/pbs/PBTable.tsx
index 6c859b3d7..aadc52f87 100644
--- a/client/src/components/tables/pbs/PBTable.tsx
+++ b/client/src/components/tables/pbs/PBTable.tsx
@@ -40,7 +40,7 @@ export default function PBTable({
playtype: Playtype;
game: Game;
alg?: ScoreCalculatedDataLookup[I];
- defaultRankingViewMode?: RankingViewMode;
+ defaultRankingViewMode?: RankingViewMode | null;
}) {
const defaultRating = useScoreRatingAlg(game, playtype);
diff --git a/client/src/components/util/usePreferredRanking.tsx b/client/src/components/util/usePreferredRanking.tsx
new file mode 100644
index 000000000..54ec630a9
--- /dev/null
+++ b/client/src/components/util/usePreferredRanking.tsx
@@ -0,0 +1,10 @@
+import { UGPTSettings } from "tachi-common";
+import useLUGPTSettings from "./useLUGPTSettings";
+
+export default function usePreferredRanking():
+ | UGPTSettings["preferences"]["preferredRanking"]
+ | null {
+ const { settings } = useLUGPTSettings();
+
+ return settings?.preferences.preferredRanking ?? null;
+}
diff --git a/common/src/types.ts b/common/src/types.ts
index 549c2f740..6845c0211 100644
--- a/common/src/types.ts
+++ b/common/src/types.ts
@@ -1471,6 +1471,7 @@ export interface UGPTSettings extends MongoDBDo
stats: Array;
scoreBucket: "grade" | "lamp" | null;
defaultTable: string | null;
+ preferredRanking: "global" | "rival" | null;
gameSpecific: UGPTSpecificPreferences[I];
};
rivals: Array;
diff --git a/server/src/lib/game-settings/create-game-settings.ts b/server/src/lib/game-settings/create-game-settings.ts
index 35f030966..d9e81c14b 100644
--- a/server/src/lib/game-settings/create-game-settings.ts
+++ b/server/src/lib/game-settings/create-game-settings.ts
@@ -43,6 +43,7 @@ export async function CreateGameSettings(userID: integer, game: Game, playtype:
preferredScoreAlg: null,
scoreBucket: null,
defaultTable: null,
+ preferredRanking: null,
stats: [],
gameSpecific,
},
diff --git a/server/src/lib/migration/migrations.ts b/server/src/lib/migration/migrations.ts
index 6e3fbb1c5..16eeaa821 100644
--- a/server/src/lib/migration/migrations.ts
+++ b/server/src/lib/migration/migrations.ts
@@ -1,3 +1,4 @@
+import UGPTAddPreferredRanking from "./migrations/add-preferredRanking-to-ugpt";
import UGPTRivalsMigration from "./migrations/add-rivals-to-ugpt";
import RecalcBrokenIIDXNotecounts from "./migrations/recalc-broken-iidx-notecounts";
import RemoveIIDXBeginners from "./migrations/remove-iidx-beginners";
@@ -27,7 +28,7 @@ export const FAKE_MIGRATION: Migration = {
const REGISTERED_MIGRATIONS: Array =
Environment.nodeEnv === "test"
? [FAKE_MIGRATION]
- : [UGPTRivalsMigration, RemoveMultifolderStats];
+ : [UGPTRivalsMigration, RemoveMultifolderStats, UGPTAddPreferredRanking];
// only apply type-specific migrations if we're not in testing
if (Environment.nodeEnv !== "test") {
diff --git a/server/src/lib/migration/migrations/add-preferredRanking-to-ugpt.ts b/server/src/lib/migration/migrations/add-preferredRanking-to-ugpt.ts
new file mode 100644
index 000000000..8ec001cc5
--- /dev/null
+++ b/server/src/lib/migration/migrations/add-preferredRanking-to-ugpt.ts
@@ -0,0 +1,28 @@
+import db from "external/mongo/db";
+import type { Migration } from "utils/types";
+
+const migration: Migration = {
+ id: "add-preferredRanking-to-ugpt",
+ up: async () => {
+ await db["game-settings"].update(
+ {},
+ {
+ $set: {
+ "preferences.preferredRanking": null,
+ },
+ },
+ { multi: true }
+ );
+ },
+ down: async () => {
+ await db["game-settings"].update(
+ {},
+ {
+ $unset: { "preferences.preferredRanking": 1 },
+ },
+ { multi: true }
+ );
+ },
+};
+
+export default migration;
diff --git a/server/src/server/router/api/v1/users/_userID/games/_game/_playtype/settings/router.ts b/server/src/server/router/api/v1/users/_userID/games/_game/_playtype/settings/router.ts
index 06b18214e..bf1be647e 100644
--- a/server/src/server/router/api/v1/users/_userID/games/_game/_playtype/settings/router.ts
+++ b/server/src/server/router/api/v1/users/_userID/games/_game/_playtype/settings/router.ts
@@ -53,6 +53,7 @@ router.patch(
preferredSessionAlg: p.optional(p.nullable(p.isIn(gptConfig.sessionRatingAlgs))),
preferredProfileAlg: p.optional(p.nullable(p.isIn(gptConfig.profileRatingAlgs))),
defaultTable: "*?string",
+ preferredRanking: optNull(p.isIn("global", "rival")),
// This is handled with game-specific schema validation below.
gameSpecific: optNull(gameSpecificSchema),
@@ -104,6 +105,10 @@ router.patch(
updateQuery[`preferences.defaultTable`] = body.defaultTable;
}
+ if (body.preferredRanking !== undefined) {
+ updateQuery[`preferences.preferredRanking`] = body.preferredRanking;
+ }
+
if (body.gameSpecific) {
for (const [key, value] of Object.entries(body.gameSpecific)) {
// @ts-expect-error This is a very hacky way of applying changes.