From 67c5b16976017112d0809fe2fa030ff613361ed4 Mon Sep 17 00:00:00 2001
From: zkldi <20380519+zkldi@users.noreply.github.com>
Date: Mon, 9 Jan 2023 23:12:44 +0000
Subject: [PATCH] checkpoint: 27
---
.../src/components/user/UGPTStatContainer.tsx | 2 +-
.../src/components/user/UGPTStatCreator.tsx | 4 +-
.../src/components/user/UGPTStatShowcase.tsx | 14 ++--
common/src/config/config.ts | 1 -
common/src/lib/schemas.ts | 11 ++-
common/src/types/documents.ts | 11 ++-
common/src/types/metrics.ts | 6 ++
server/src/external/mongo/indexes.ts | 10 ++-
.../score-import/framework/pb/process-pbs.ts | 23 +++++-
.../framework/score-importing/derivers.ts | 2 +-
.../score-importing/hydrate-score.ts | 4 +-
.../file/solid-state-squad/converter.ts | 1 +
server/src/lib/score-mutation/update-score.ts | 2 +-
server/src/lib/showcase/evaluator.ts | 81 +++++++++++--------
server/src/lib/showcase/get-stats.test.ts | 4 +-
server/src/lib/showcase/get-stats.ts | 16 +++-
server/src/lib/showcase/showcase.test.ts | 10 +--
server/src/lib/targets/goal-utils.ts | 6 +-
server/src/lib/targets/goals.ts | 2 +-
server/src/server/router/api/v1/auth/auth.ts | 17 ++--
.../src/server/router/api/v1/auth/router.ts | 2 +-
.../@gameSpecificRoutes/jubeat/router.ts | 2 +-
.../games/_game/_playtype/settings/router.ts | 5 +-
.../_game/_playtype/showcase/router.test.ts | 6 +-
.../games/_game/_playtype/showcase/router.ts | 10 ++-
server/src/test-utils/test-data.ts | 1 -
.../src/utils/calculations/recalc-scores.ts | 2 +-
server/src/utils/scores.ts | 6 +-
28 files changed, 163 insertions(+), 98 deletions(-)
diff --git a/client/src/components/user/UGPTStatContainer.tsx b/client/src/components/user/UGPTStatContainer.tsx
index 1dcd5ec7b..b5db1f06a 100644
--- a/client/src/components/user/UGPTStatContainer.tsx
+++ b/client/src/components/user/UGPTStatContainer.tsx
@@ -17,7 +17,7 @@ export default function UGPTStatContainer({
const searchParams = new URLSearchParams();
searchParams.set("mode", stat.mode);
- searchParams.set("property", stat.property);
+ searchParams.set("property", stat.metric);
if (stat.mode === "chart") {
searchParams.set("chartID", stat.chartID);
diff --git a/client/src/components/user/UGPTStatCreator.tsx b/client/src/components/user/UGPTStatCreator.tsx
index 2af350a6b..b86095f62 100644
--- a/client/src/components/user/UGPTStatCreator.tsx
+++ b/client/src/components/user/UGPTStatCreator.tsx
@@ -48,13 +48,13 @@ export default function UGPTStatCreator({
if (values.mode === "chart") {
stat = {
mode: "chart",
- property: values.property as ShowcaseStatDetails["property"],
+ metric: values.property as ShowcaseStatDetails["metric"],
chartID: values.chartID ?? "",
};
} else if (values.mode === "folder") {
stat = {
mode: "folder",
- property: values.property as "lamp" | "score" | "percent" | "grade",
+ metric: values.property as "lamp" | "score" | "percent" | "grade",
folderID: values.folderID ?? "",
gte,
};
diff --git a/client/src/components/user/UGPTStatShowcase.tsx b/client/src/components/user/UGPTStatShowcase.tsx
index e6316dbc0..68aee2c29 100644
--- a/client/src/components/user/UGPTStatShowcase.tsx
+++ b/client/src/components/user/UGPTStatShowcase.tsx
@@ -266,7 +266,7 @@ function StatDelta({
v1: number;
v2?: number;
mode: "folder" | "chart";
- property: UGPTPreferenceStatsReturn["stat"]["property"];
+ property: UGPTPreferenceStatsReturn["stat"]["metric"];
game: Game;
playtype: Playtype;
}) {
@@ -397,15 +397,15 @@ export function StatDisplay({
{FormatChart(game, song, chart)}
- {UppercaseFirst(stat.property)}:{" "}
- {FormatPropertyGTE(game, playtype, stat.property, result.value)}
+ {UppercaseFirst(stat.metric)}:{" "}
+ {FormatPropertyGTE(game, playtype, stat.metric, result.value)}
{user && user.id !== reqUser.id && (
@@ -431,8 +431,8 @@ export function StatDisplay({
{headerStr}
- {UppercaseFirst(stat.property)} >={" "}
- {FormatPropertyGTE(game, playtype, stat.property, stat.gte)}
+ {UppercaseFirst(stat.metric)} >={" "}
+ {FormatPropertyGTE(game, playtype, stat.metric, stat.gte)}
{result.value}
@@ -447,7 +447,7 @@ export function StatDisplay({
v1={statData.result.value}
v2={compareData?.result.value}
mode={stat.mode}
- property={stat.property}
+ property={stat.metric}
game={game}
playtype={playtype}
/>
diff --git a/common/src/config/config.ts b/common/src/config/config.ts
index d299f2cde..5400337ef 100644
--- a/common/src/config/config.ts
+++ b/common/src/config/config.ts
@@ -20,7 +20,6 @@ import type {
GamePTConfig,
Playtype,
Playtypes,
- ProvidedMetrics,
} from "../types/game-config";
import type { INTERNAL_GAME_CONFIG, INTERNAL_GAME_PT_CONFIG } from "../types/internals";
import type { ConfScoreMetric } from "../types/metrics";
diff --git a/common/src/lib/schemas.ts b/common/src/lib/schemas.ts
index 773a952f2..da7802e31 100644
--- a/common/src/lib/schemas.ts
+++ b/common/src/lib/schemas.ts
@@ -39,7 +39,11 @@ function prSchemaFnWrap(schema: PrudenceSchema) {
};
}
-const PR_GAME_STATS = (game: Game, playtype: Playtypes[Game], gptConfig: INTERNAL_GAME_PT_CONFIG) => ({
+const PR_GAME_STATS = (
+ game: Game,
+ playtype: Playtypes[Game],
+ gptConfig: INTERNAL_GAME_PT_CONFIG
+) => ({
userID: p.isPositiveNonZeroInteger,
game: p.is(game),
playtype: p.is(playtype),
@@ -77,7 +81,9 @@ const extractGPTIDString = (self: unknown) => {
// Playtype might be undefined in the case where the string contains no colon.
if (playtype === undefined || !IsValidPlaytype(game, playtype)) {
- throw new Error(`Expected valid playtype -- got ${playtype} from gptString ${s.gptString}.`);
+ throw new Error(
+ `Expected valid playtype -- got ${playtype} from gptString ${s.gptString}.`
+ );
}
return { game, playtype };
@@ -652,7 +658,6 @@ const PRE_SCHEMAS = {
status: p.nullable(p.isBoundedString(3, 140)),
customPfpLocation: "?string",
customBannerLocation: "?string",
- clan: p.nullable(p.isBoundedString(2, 4)),
lastSeen: p.isPositiveInteger,
badges: [p.isIn("beta", "alpha", "devTeam")],
authLevel: p.isBoundedInteger(UserAuthLevels.BANNED, UserAuthLevels.ADMIN),
diff --git a/common/src/types/documents.ts b/common/src/types/documents.ts
index 0ad0362f0..02818c406 100644
--- a/common/src/types/documents.ts
+++ b/common/src/types/documents.ts
@@ -319,7 +319,6 @@ export interface UserDocument {
status: string | null;
customPfpLocation: string | null;
customBannerLocation: string | null;
- clan: string | null; // todo
badges: Array;
authLevel: UserAuthLevels;
}
@@ -609,14 +608,20 @@ export type ShowcaseStatDetails = ShowcaseStatChart | ShowcaseStatFolder;
export interface ShowcaseStatFolder {
mode: "folder";
folderID: string;
- property: "grade" | "lamp" | "percent" | "score";
+
+ // should be a valid metric for the showcase this game is for
+ // this is not checked by the typesystem though. sorry!
+ metric: string;
gte: number;
}
export interface ShowcaseStatChart {
mode: "chart";
chartID: string;
- property: "grade" | "lamp" | "percent" | "playcount" | "score";
+
+ // should be a valid metric for the showcase this game is for
+ // this is not checked by the typesystem though. sorry!
+ metric: string;
}
export interface UGPTSettingsDocument {
diff --git a/common/src/types/metrics.ts b/common/src/types/metrics.ts
index b2b4edb71..ecc59ae6e 100644
--- a/common/src/types/metrics.ts
+++ b/common/src/types/metrics.ts
@@ -24,12 +24,18 @@ interface ConfDecimalScoreMetricNormal {
type: "DECIMAL";
validate: (v: number) => string | true;
+
+ // This exists to allow DecimalScoreMetric.chartDependentMax.
+ chartDependentMax?: never;
}
interface ConfIntegerScoreMetricNormal {
type: "INTEGER";
validate: (v: number) => string | true;
+
+ // see above
+ chartDependentMax?: never;
}
interface ConfDecimalScoreMetricChartDependent {
diff --git a/server/src/external/mongo/indexes.ts b/server/src/external/mongo/indexes.ts
index 0361dfa55..6f0396544 100644
--- a/server/src/external/mongo/indexes.ts
+++ b/server/src/external/mongo/indexes.ts
@@ -2,7 +2,8 @@
import CreateLogCtx from "lib/logger/logger";
import { TachiConfig } from "lib/setup/config";
import monk from "monk";
-import { Random20Hex } from "utils/misc";
+import { GAME_PT_CONFIGS } from "tachi-common";
+import { DedupeArr, Random20Hex } from "utils/misc";
import type { Databases } from "./db";
import type { IndexOptions } from "mongodb";
import type { IMonkManager } from "monk";
@@ -20,6 +21,8 @@ function index(fields: Record, options?: IndexOptions) {
const UNIQUE = { unique: true };
+const allDefaultMetrics = DedupeArr(Object.values(GAME_PT_CONFIGS).map((e) => e.defaultMetric));
+
// NOTE: INDEXES REMOVED FROM HERE WILL **NOT** AUTOMATICALLY UPDATE.
// YOU NEED TO RUN src/scripts/set-indexes.ts --reset TO REMOVE INDEXES.
// (indexes added will automatically apply on tachi-server boot, though).
@@ -34,7 +37,10 @@ const staticIndexes: Partial>> = {
],
"personal-bests": [
index({ chartID: 1, userID: 1 }, UNIQUE),
- index({ chartID: 1, [`scoreData.${gptConfig.defaultMetric}`]: 1 }),
+
+ // one index for every default metric, why not.
+ ...allDefaultMetrics.map((e) => index({ chartID: 1, [`scoreData.${e}`]: 1 })),
+
index({ userID: 1, game: 1, playtype: 1 }),
// activity
diff --git a/server/src/lib/score-import/framework/pb/process-pbs.ts b/server/src/lib/score-import/framework/pb/process-pbs.ts
index 22634f341..b9166315c 100644
--- a/server/src/lib/score-import/framework/pb/process-pbs.ts
+++ b/server/src/lib/score-import/framework/pb/process-pbs.ts
@@ -1,5 +1,7 @@
import { CreatePBDoc, UpdateChartRanking } from "./create-pb-doc";
import db from "external/mongo/db";
+import { GetGPTString } from "tachi-common";
+import { GetChartForIDGuaranteed } from "utils/db";
import type { PBScoreDocumentNoRank } from "./create-pb-doc";
import type { KtLogger } from "lib/logger/logger";
import type { Game, integer, Playtype } from "tachi-common";
@@ -18,10 +20,16 @@ export async function ProcessPBs(
return;
}
+ const gpt = GetGPTString(game, playtype);
+
const promises = [];
for (const chartID of chartIDs) {
- promises.push(CreatePBDoc(userID, chartID, logger));
+ promises.push(
+ GetChartForIDGuaranteed(game, chartID).then((chart) =>
+ CreatePBDoc(gpt, userID, chart, logger)
+ )
+ );
}
const pbDocsReturn = await Promise.all(promises);
@@ -49,7 +57,18 @@ export async function ProcessPBs(
pbDocs.map((e) => ({
updateOne: {
filter: { chartID: e.chartID, userID: e.userID },
- update: { $set: e },
+ update: {
+ $set: {
+ ...e,
+
+ // stub out ranking data with some invalid nonsense.
+ rankingData: {
+ outOf: 0,
+ rank: 0,
+ rivalRank: null,
+ },
+ },
+ },
upsert: true,
},
})),
diff --git a/server/src/lib/score-import/framework/score-importing/derivers.ts b/server/src/lib/score-import/framework/score-importing/derivers.ts
index 1174e9525..ff295c6c5 100644
--- a/server/src/lib/score-import/framework/score-importing/derivers.ts
+++ b/server/src/lib/score-import/framework/score-importing/derivers.ts
@@ -2,7 +2,7 @@ import { InternalFailure } from "../common/converter-failures";
import { GPT_SERVER_IMPLEMENTATIONS } from "game-implementations/game-implementations";
import { GetGPTConfig } from "tachi-common";
import type { DryScore, DryScoreData } from "../common/types";
-import type { GPTDerivers } from "./types";
+import type { GPTDerivers } from "game-implementations/types";
import type { KtLogger } from "lib/logger/logger";
import type {
ChartDocument,
diff --git a/server/src/lib/score-import/framework/score-importing/hydrate-score.ts b/server/src/lib/score-import/framework/score-importing/hydrate-score.ts
index 8a7ba94a1..d8b6be53f 100644
--- a/server/src/lib/score-import/framework/score-importing/hydrate-score.ts
+++ b/server/src/lib/score-import/framework/score-importing/hydrate-score.ts
@@ -1,5 +1,5 @@
-import { CreateScoreCalcData } from "../calculated-data/score";
import { CreateFullScoreData } from "./derivers";
+import { CreateScoreCalcData } from "../calculated-data/score";
import { GetGPTString } from "tachi-common";
import type { DryScore } from "../common/types";
import type { KtLogger } from "lib/logger/logger";
@@ -22,7 +22,7 @@ export function HydrateScore(
const scoreData = CreateFullScoreData(gpt, dryScore.scoreData, chart, logger);
- const calculatedData = CreateScoreCalcData(dryScore, chart);
+ const calculatedData = CreateScoreCalcData(dryScore.game, dryScore.scoreData, chart);
const score: ScoreDocument = {
...dryScore,
diff --git a/server/src/lib/score-import/import-types/file/solid-state-squad/converter.ts b/server/src/lib/score-import/import-types/file/solid-state-squad/converter.ts
index a330c6de6..03c337b8c 100644
--- a/server/src/lib/score-import/import-types/file/solid-state-squad/converter.ts
+++ b/server/src/lib/score-import/import-types/file/solid-state-squad/converter.ts
@@ -10,6 +10,7 @@ import type { DryScore } from "../../../framework/common/types";
import type { ConverterFunction } from "../../common/types";
import type { S3Score } from "./types";
import type { Difficulties, Playtypes, Versions } from "tachi-common";
+import type { GetEnumValue } from "tachi-common/types/metrics";
import type { EmptyObject } from "utils/types";
export function ParseDifficulty(diff: S3Score["diff"]): {
diff --git a/server/src/lib/score-mutation/update-score.ts b/server/src/lib/score-mutation/update-score.ts
index c99b61170..c1805c40c 100644
--- a/server/src/lib/score-mutation/update-score.ts
+++ b/server/src/lib/score-mutation/update-score.ts
@@ -76,7 +76,7 @@ export default async function UpdateScore(
logger.verbose("Received Update Score request.");
// eslint-disable-next-line require-atomic-updates
- newScore.calculatedData = CreateScoreCalcData(newScore, chart);
+ newScore.calculatedData = CreateScoreCalcData(newScore.game, newScore.scoreData, chart);
try {
// Having _id defined will cause this to throw, causing it to not apply
diff --git a/server/src/lib/showcase/evaluator.ts b/server/src/lib/showcase/evaluator.ts
index ccc27d066..75f12cebb 100644
--- a/server/src/lib/showcase/evaluator.ts
+++ b/server/src/lib/showcase/evaluator.ts
@@ -1,13 +1,16 @@
import db from "external/mongo/db";
+import { GetGPTConfig } from "tachi-common";
import { GetFolderChartIDs } from "utils/folder";
import type {
- integer,
- ShowcaseStatDetails,
+ GPTString,
ShowcaseStatChart,
+ ShowcaseStatDetails,
ShowcaseStatFolder,
+ integer,
} from "tachi-common";
export function EvaluateShowcaseStat(
+ gpt: GPTString,
details: ShowcaseStatDetails,
userID: integer
): Promise<{
@@ -16,9 +19,9 @@ export function EvaluateShowcaseStat(
}> {
switch (details.mode) {
case "chart":
- return EvaluateShowcaseChartStat(details, userID);
+ return EvaluateShowcaseChartStat(gpt, details, userID);
case "folder":
- return EvaluateShowcaseFolderStat(details, userID);
+ return EvaluateShowcaseFolderStat(gpt, details, userID);
default:
// @ts-expect-error This should never happen anyway -- this ignore ignores a 'never' result.
@@ -26,13 +29,17 @@ export function EvaluateShowcaseStat(
}
}
-async function EvaluateShowcaseChartStat(details: ShowcaseStatChart, userID: integer) {
+async function EvaluateShowcaseChartStat(
+ gpt: GPTString,
+ details: ShowcaseStatChart,
+ userID: integer
+) {
// requires special handling
- if (details.property === "playcount") {
+ if (details.metric === "playcount") {
return { value: await db.scores.count({ chartID: details.chartID, userID }) };
}
- const mongoProp = PropToMongoProp(details.property);
+ const mongoProp = PropToMongoProp(gpt, details.metric);
const pb = await db["personal-bests"].findOne(
{ chartID: details.chartID, userID },
@@ -43,12 +50,30 @@ async function EvaluateShowcaseChartStat(details: ShowcaseStatChart, userID: int
return { value: null };
}
- const scProp = PropToScoreDataProp(details.property);
+ const metric = details.metric;
- return { value: pb.scoreData[scProp] };
+ const gptConfig = GetGPTConfig(gpt);
+
+ const scoreMetricConfig = gptConfig.providedMetrics[metric] ?? gptConfig.derivedMetrics[metric];
+
+ if (!scoreMetricConfig) {
+ throw new Error(`Invalid metric of ${metric} passed for game ${gpt}.`);
+ }
+
+ if (scoreMetricConfig.type === "ENUM") {
+ // @ts-expect-error guaranteed to be correct
+ return { value: pb.scoreData.enumIndexes[metric] };
+ }
+
+ // @ts-expect-error guaranteed to be correct
+ return { value: pb.scoreData[metric] };
}
-async function EvaluateShowcaseFolderStat(details: ShowcaseStatFolder, userID: integer) {
+async function EvaluateShowcaseFolderStat(
+ gpt: GPTString,
+ details: ShowcaseStatFolder,
+ userID: integer
+) {
let chartIDs;
if (Array.isArray(details.folderID)) {
@@ -57,7 +82,7 @@ async function EvaluateShowcaseFolderStat(details: ShowcaseStatFolder, userID: i
chartIDs = await GetFolderChartIDs(details.folderID);
}
- const mongoProp = PropToMongoProp(details.property);
+ const mongoProp = PropToMongoProp(gpt, details.metric);
const value = await db["personal-bests"].count({
userID,
@@ -70,28 +95,18 @@ async function EvaluateShowcaseFolderStat(details: ShowcaseStatFolder, userID: i
return { value, outOf: chartIDs.length };
}
-function PropToMongoProp(prop: "grade" | "lamp" | "percent" | "score") {
- switch (prop) {
- case "score":
- return "scoreData.score";
- case "lamp":
- return "scoreData.lampIndex";
- case "grade":
- return "scoreData.gradeIndex";
- case "percent":
- return [`scoreData.${gptConfig.defaultMetric}`];
- }
-}
+function PropToMongoProp(gpt: GPTString, metric: string) {
+ const gptConfig = GetGPTConfig(gpt);
-function PropToScoreDataProp(prop: "grade" | "lamp" | "percent" | "score") {
- switch (prop) {
- case "score":
- return "score";
- case "lamp":
- return "lampIndex";
- case "grade":
- return "gradeIndex";
- case "percent":
- return "percent";
+ const scoreMetricConfig = gptConfig.providedMetrics[metric] ?? gptConfig.derivedMetrics[metric];
+
+ if (!scoreMetricConfig) {
+ throw new Error(`Invalid metric of ${metric} passed for game ${gpt}.`);
}
+
+ if (scoreMetricConfig.type === "ENUM") {
+ return `scoreData.enumIndexes.${metric}`;
+ }
+
+ return `scoreData.${metric}`;
}
diff --git a/server/src/lib/showcase/get-stats.test.ts b/server/src/lib/showcase/get-stats.test.ts
index 34f05bc45..56ec15e84 100644
--- a/server/src/lib/showcase/get-stats.test.ts
+++ b/server/src/lib/showcase/get-stats.test.ts
@@ -31,13 +31,13 @@ t.test("#EvalulateUsersStatsShowcase", (t) => {
{
folderID: TestingIIDXFolderSP10.folderID,
mode: "folder",
- property: "lamp",
+ metric: "lamp",
gte: IIDX_LAMPS.HARD_CLEAR,
},
{
chartID: Testing511SPA.chartID,
mode: "chart",
- property: "score",
+ metric: "score",
},
],
gameSpecific: {
diff --git a/server/src/lib/showcase/get-stats.ts b/server/src/lib/showcase/get-stats.ts
index c8369e33d..d98fab2c3 100644
--- a/server/src/lib/showcase/get-stats.ts
+++ b/server/src/lib/showcase/get-stats.ts
@@ -2,7 +2,8 @@ import { EvaluateShowcaseStat } from "./evaluator";
import { GetRelatedStatDocuments } from "./get-related";
import db from "external/mongo/db";
import CreateLogCtx from "lib/logger/logger";
-import type { integer, Game, Playtype, ShowcaseStatDetails } from "tachi-common";
+import { GetGPTString } from "tachi-common";
+import type { integer, Game, Playtype, ShowcaseStatDetails, GPTString } from "tachi-common";
const logger = CreateLogCtx(__filename);
@@ -34,16 +35,23 @@ export async function EvaluateUsersStatsShowcase(
);
}
+ const gpt = GetGPTString(game, playtype);
+
const results = await Promise.all(
- settings.preferences.stats.map((details) => EvaluateStats(details, userID, game))
+ settings.preferences.stats.map((details) => EvaluateStats(gpt, details, userID, game))
);
return results;
}
-async function EvaluateStats(details: ShowcaseStatDetails, userID: integer, game: Game) {
+async function EvaluateStats(
+ gpt: GPTString,
+ details: ShowcaseStatDetails,
+ userID: integer,
+ game: Game
+) {
const [result, related] = await Promise.all([
- EvaluateShowcaseStat(details, userID),
+ EvaluateShowcaseStat(gpt, details, userID),
GetRelatedStatDocuments(details, game),
]);
diff --git a/server/src/lib/showcase/showcase.test.ts b/server/src/lib/showcase/showcase.test.ts
index ea30c891f..e35534127 100644
--- a/server/src/lib/showcase/showcase.test.ts
+++ b/server/src/lib/showcase/showcase.test.ts
@@ -18,19 +18,19 @@ t.test("#RemoveStaleFolderShowcaseStats", (t) => {
{
mode: "chart",
chartID: "foo",
- property: "grade",
+ metric: "grade",
},
{
mode: "folder",
folderID: "REMOVED_FOLDER",
gte: 1,
- property: "lamp",
+ metric: "lamp",
},
{
mode: "folder",
folderID: "NORMAL_FOLDER",
gte: 1,
- property: "lamp",
+ metric: "lamp",
},
],
},
@@ -42,13 +42,13 @@ t.test("#RemoveStaleFolderShowcaseStats", (t) => {
{
mode: "chart",
chartID: "foo",
- property: "grade",
+ metric: "grade",
},
{
mode: "folder",
folderID: "REMOVED_FOLDER",
gte: 1,
- property: "lamp",
+ metric: "lamp",
},
],
},
diff --git a/server/src/lib/targets/goal-utils.ts b/server/src/lib/targets/goal-utils.ts
index 1f81c7193..55a904315 100644
--- a/server/src/lib/targets/goal-utils.ts
+++ b/server/src/lib/targets/goal-utils.ts
@@ -1,5 +1,5 @@
import db from "external/mongo/db";
-import { FormatGame, GetGamePTConfig, GetSpecificGPTConfig } from "tachi-common";
+import { FormatGame, GetGPTString, GetGamePTConfig, GetSpecificGPTConfig } from "tachi-common";
import { GetFolderForIDGuaranteed, HumaniseChartID } from "utils/db";
import { GetFolderChartIDs } from "utils/folder";
import { FormatMaxDP, HumanisedJoinArray } from "utils/misc";
@@ -11,7 +11,9 @@ export async function CreateGoalTitle(
game: Game,
playtype: Playtype
) {
- const formattedCriteria = FormatCriteria(criteria, game, playtype);
+ const gptString = GetGPTString(game, playtype);
+
+ const formattedCriteria = FormatCriteria(criteria, gptString);
const datasetName = await FormatCharts(charts, criteria, game);
diff --git a/server/src/lib/targets/goals.ts b/server/src/lib/targets/goals.ts
index 3d37e7d9d..124eb37ce 100644
--- a/server/src/lib/targets/goals.ts
+++ b/server/src/lib/targets/goals.ts
@@ -3,7 +3,7 @@ import db from "external/mongo/db";
import fjsh from "fast-json-stable-hash";
import { SubscribeFailReasons } from "lib/constants/err-codes";
import CreateLogCtx from "lib/logger/logger";
-import { FormatGame, GenericFormatGradeDelta, GetGamePTConfig } from "tachi-common";
+import { FormatGame, GetGamePTConfig } from "tachi-common";
import { GetFolderChartIDs } from "utils/folder";
import { IsNullish } from "utils/misc";
import type { KtLogger } from "lib/logger/logger";
diff --git a/server/src/server/router/api/v1/auth/auth.ts b/server/src/server/router/api/v1/auth/auth.ts
index 835b3b724..960a3e796 100644
--- a/server/src/server/router/api/v1/auth/auth.ts
+++ b/server/src/server/router/api/v1/auth/auth.ts
@@ -1,14 +1,14 @@
import bcrypt from "bcryptjs";
import db from "external/mongo/db";
import CreateLogCtx from "lib/logger/logger";
-import { Environment, ServerConfig } from "lib/setup/config";
+import { ServerConfig } from "lib/setup/config";
import { p } from "prudence";
import { UserAuthLevels } from "tachi-common";
import nodeFetch from "utils/fetch";
import { Random20Hex } from "utils/misc";
import { CreateURLWithParams } from "utils/url";
import { FormatUserDoc } from "utils/user";
-import type { integer, UserDocument, UserSettings } from "tachi-common";
+import type { integer, UserDocument, UserSettingsDocument } from "tachi-common";
import type { PrivateUserInfoDocument } from "utils/types";
const logger = CreateLogCtx(__filename);
@@ -60,7 +60,7 @@ export async function AddNewInvite(user: UserDocument) {
return result;
}
-export const DEFAULT_USER_SETTINGS: UserSettings["preferences"] = {
+export const DEFAULT_USER_SETTINGS: UserSettingsDocument["preferences"] = {
developerMode: false,
advancedMode: false,
invisible: false,
@@ -87,7 +87,6 @@ export async function AddNewUser(
username,
usernameLowercase: username.toLowerCase(),
about: "I'm a fairly nondescript person.",
- clan: null,
socialMedia: {},
status: null,
customBannerLocation: null,
@@ -119,13 +118,13 @@ export function InsertPrivateUserInfo(userID: integer, hashedPassword: string, e
export function InsertDefaultUserSettings(userID: integer) {
logger.verbose(`Inserting default settings for ${userID}.`);
- const userSettings: UserSettings = {
+ const UserSettingsDocument: UserSettingsDocument = {
userID,
following: [],
preferences: DEFAULT_USER_SETTINGS,
};
- return db["user-settings"].insert(userSettings);
+ return db["user-settings"].insert(UserSettingsDocument);
}
export async function ValidateCaptcha(
@@ -168,7 +167,11 @@ export async function ValidateCaptcha(
return gcr.success;
}
-export function MountAuthCookie(req: Express.Request, user: UserDocument, settings: UserSettings) {
+export function MountAuthCookie(
+ req: Express.Request,
+ user: UserDocument,
+ settings: UserSettingsDocument
+) {
req.session.tachi = {
user,
settings,
diff --git a/server/src/server/router/api/v1/auth/router.ts b/server/src/server/router/api/v1/auth/router.ts
index 3e65b21cc..72cb788af 100644
--- a/server/src/server/router/api/v1/auth/router.ts
+++ b/server/src/server/router/api/v1/auth/router.ts
@@ -13,7 +13,7 @@ import db from "external/mongo/db";
import { SendEmail } from "lib/email/client";
import { EmailFormatResetPassword, EmailFormatVerifyEmail } from "lib/email/formats";
import CreateLogCtx from "lib/logger/logger";
-import { Environment, ServerConfig, TachiConfig } from "lib/setup/config";
+import { Environment, ServerConfig } from "lib/setup/config";
import { p } from "prudence";
import prValidate from "server/middleware/prudence-validate";
import {
diff --git a/server/src/server/router/api/v1/users/_userID/games/@gameSpecificRoutes/jubeat/router.ts b/server/src/server/router/api/v1/users/_userID/games/@gameSpecificRoutes/jubeat/router.ts
index ab43337dc..bea5f4557 100644
--- a/server/src/server/router/api/v1/users/_userID/games/@gameSpecificRoutes/jubeat/router.ts
+++ b/server/src/server/router/api/v1/users/_userID/games/@gameSpecificRoutes/jubeat/router.ts
@@ -1,5 +1,5 @@
import { Router } from "express";
-import { GetPBsForJubility } from "lib/score-import/framework/calculated-data/profile";
+import { GetPBsForJubility } from "game-implementations/games/jubeat";
import { GetRelevantSongsAndCharts } from "utils/db";
import { GetUser } from "utils/req-tachi-data";
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 c32a79f0b..4f003109f 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
@@ -4,8 +4,7 @@ import db from "external/mongo/db";
import CreateLogCtx from "lib/logger/logger";
import { p } from "prudence";
import { RequirePermissions } from "server/middleware/auth";
-import { GetGamePTConfig } from "tachi-common";
-import { PR_GAMESPECIFIC_SETTINGS } from "tachi-common/lib/schemas";
+import { GetGamePTConfig, PrudenceZodShim } from "tachi-common";
import { FormatPrError, optNull } from "utils/prudence";
import { GetUGPT } from "utils/req-tachi-data";
import { FormatUserDoc } from "utils/user";
@@ -31,7 +30,7 @@ router.patch(
const gptConfig = GetGamePTConfig(game, playtype);
- const gameSpecificSchema = PR_GAMESPECIFIC_SETTINGS(game);
+ const gameSpecificSchema = PrudenceZodShim(gptConfig.preferences);
const err = p(req.safeBody, {
preferredScoreAlg: p.optional(p.nullable(p.isIn(gptConfig.scoreRatingAlgs))),
diff --git a/server/src/server/router/api/v1/users/_userID/games/_game/_playtype/showcase/router.test.ts b/server/src/server/router/api/v1/users/_userID/games/_game/_playtype/showcase/router.test.ts
index e18a0bd7b..75c7cb600 100644
--- a/server/src/server/router/api/v1/users/_userID/games/_game/_playtype/showcase/router.test.ts
+++ b/server/src/server/router/api/v1/users/_userID/games/_game/_playtype/showcase/router.test.ts
@@ -30,13 +30,13 @@ const SetFolders = async () => {
{
folderID: TestingIIDXFolderSP10.folderID,
mode: "folder",
- property: "lamp",
+ metric: "lamp",
gte: IIDX_LAMPS.HARD_CLEAR,
},
{
chartID: Testing511SPA.chartID,
mode: "chart",
- property: "score",
+ metric: "score",
},
],
gameSpecific: {
@@ -96,7 +96,7 @@ t.test("GET /api/v1/users/:userID/games/:game/:playtype/showcase", (t) => {
{
mode: "folder",
folderID: TestingIIDXFolderSP10.folderID,
- property: "score",
+ metric: "score",
gte: 1480,
},
],
diff --git a/server/src/server/router/api/v1/users/_userID/games/_game/_playtype/showcase/router.ts b/server/src/server/router/api/v1/users/_userID/games/_game/_playtype/showcase/router.ts
index 25249686d..82593ea33 100644
--- a/server/src/server/router/api/v1/users/_userID/games/_game/_playtype/showcase/router.ts
+++ b/server/src/server/router/api/v1/users/_userID/games/_game/_playtype/showcase/router.ts
@@ -6,7 +6,7 @@ import { EvaluateUsersStatsShowcase } from "lib/showcase/get-stats";
import { p } from "prudence";
import { RequirePermissions } from "server/middleware/auth";
import { RequireAuthedAsUser } from "server/router/api/v1/users/_userID/middleware";
-import { FormatGame, GetGamePTConfig } from "tachi-common";
+import { FormatGame, GetGPTString, GetGamePTConfig } from "tachi-common";
import { IsRecord } from "utils/misc";
import { FormatPrError } from "utils/prudence";
import { GetUGPT } from "utils/req-tachi-data";
@@ -103,7 +103,7 @@ router.get("/custom", async (req, res) => {
stat = {
mode: "folder",
- property: req.query.property as "grade" | "lamp" | "percent" | "score",
+ metric: req.query.property as "grade" | "lamp" | "percent" | "score",
folderID,
gte: Number(req.query.gte),
};
@@ -137,7 +137,7 @@ router.get("/custom", async (req, res) => {
stat = {
mode: "chart",
- property: req.query.property as "grade" | "lamp" | "percent" | "playcount" | "score",
+ metric: req.query.property as "grade" | "lamp" | "percent" | "playcount" | "score",
chartID: req.query.chartID as string,
};
} else {
@@ -147,7 +147,9 @@ router.get("/custom", async (req, res) => {
});
}
- const result = await EvaluateShowcaseStat(stat, user.id);
+ const gpt = GetGPTString(game, playtype);
+
+ const result = await EvaluateShowcaseStat(gpt, stat, user.id);
const related = await GetRelatedStatDocuments(stat, game);
diff --git a/server/src/test-utils/test-data.ts b/server/src/test-utils/test-data.ts
index 8aa1717a2..780f92547 100644
--- a/server/src/test-utils/test-data.ts
+++ b/server/src/test-utils/test-data.ts
@@ -830,7 +830,6 @@ export const FakeOtherUser: UserDocument = {
about: "",
authLevel: 0,
badges: [],
- clan: null,
customBannerLocation: null,
customPfpLocation: null,
joinDate: 0,
diff --git a/server/src/utils/calculations/recalc-scores.ts b/server/src/utils/calculations/recalc-scores.ts
index 4198a2956..16f22c2a7 100644
--- a/server/src/utils/calculations/recalc-scores.ts
+++ b/server/src/utils/calculations/recalc-scores.ts
@@ -40,7 +40,7 @@ export async function RecalcAllScores(filter = {}) {
modifiedUsers.add(`${c.game}-${c.playtype}-${c.userID}`);
modifiedUserIDs.add(c.userID);
- const calculatedData = CreateScoreCalcData(c, chart);
+ const calculatedData = CreateScoreCalcData(c.game, c.scoreData, chart);
return { scoreID: c.scoreID, calculatedData };
},
diff --git a/server/src/utils/scores.ts b/server/src/utils/scores.ts
index 55bdb065a..23e580cfc 100644
--- a/server/src/utils/scores.ts
+++ b/server/src/utils/scores.ts
@@ -43,11 +43,7 @@ export function FilterChartsAndSongs(
}
export function GetScoreIDsFromComposed(pb: PBScoreDocument) {
- const arr = [pb.composedFrom.lampPB, pb.composedFrom.scorePB];
-
- if (pb.composedFrom.other) {
- arr.push(...pb.composedFrom.other.map((e) => e.scoreID));
- }
+ const arr = pb.composedFrom.map((e) => e.scoreID);
return DedupeArr(arr);
}