From 7c3650dd26c4e079753f1f6db63a112a1631013d Mon Sep 17 00:00:00 2001 From: zkldi <20380519+zkldi@users.noreply.github.com> Date: Fri, 6 Jan 2023 20:33:25 +0000 Subject: [PATCH] checkpoint: 14 --- client/src/types/api-returns.ts | 4 +- common/src/lib/schemas.ts | 3 + common/src/types/documents.ts | 10 +-- common/src/utils/util.ts | 18 +++- .../iidx/aix-output/parse-aix-json.ts | 89 +++++++++++++------ .../iidx/iidx-mdb-parse/merge-mdb.ts | 4 +- server/src/external/mongo/db.ts | 4 +- server/src/lib/jobs/ugs-snapshot.ts | 6 +- server/src/lib/jobs/update-bpi-data.ts | 7 +- server/src/lib/jobs/update-dp-tiers.ts | 5 +- server/src/lib/jobs/update-sp12-data.ts | 18 ++-- server/src/lib/orphan-queue/orphan-queue.ts | 4 +- .../framework/user-game-stats/rating.ts | 4 +- .../common/api-cg/museca/converter.ts | 4 +- .../common/api-cg/popn/converter.ts | 10 +-- .../common/api-cg/sdvx/converter.ts | 4 +- .../common/api-kai/iidx/converter.ts | 4 +- .../common/batch-manual/converter.ts | 4 +- .../import-types/common/batch-manual/types.ts | 4 +- .../common/eamusement-iidx-csv/parser.ts | 4 +- .../common/eamusement-iidx-csv/types.ts | 4 +- .../file/solid-state-squad/converter.ts | 45 ++++------ .../file/wacca-mypage-scraper/converter.ts | 21 ++--- .../file/wacca-mypage-scraper/parser.ts | 2 + .../import-types/ir/barbatos/types.ts | 4 +- .../import-types/ir/fervidex-static/types.ts | 4 +- .../import-types/ir/fervidex/parser.ts | 7 +- .../import-types/ir/fervidex/types.ts | 4 +- .../v1/games/_game/_playtype/charts/router.ts | 4 +- .../_userID/games/_game/_playtype/router.ts | 21 ++--- .../_game/_playtype/settings/router.test.ts | 4 +- .../charts/_chartSHA256/convert-scores.ts | 2 +- .../src/server/router/ir/usc/_playtype/usc.ts | 11 ++- server/src/utils/misc.ts | 11 +-- server/src/utils/queries/charts.ts | 18 ++-- server/src/utils/queries/stats.ts | 4 +- 36 files changed, 203 insertions(+), 173 deletions(-) diff --git a/client/src/types/api-returns.ts b/client/src/types/api-returns.ts index 09c61e3ca..4a133c085 100644 --- a/client/src/types/api-returns.ts +++ b/client/src/types/api-returns.ts @@ -24,7 +24,7 @@ import { TableDocument, ProfileRatingLookup, UserGameStats, - UserGameStatsSnapshot, + UserGameStatsSnapshotDocument, QuestDocument, QuestSubscriptionDocument, QuestlineDocument, @@ -76,7 +76,7 @@ export type UGPTPreferenceStatsReturn = related: { folder: FolderDocument }; }; -export type UGPTHistory = Omit[]; +export type UGPTHistory = Omit[]; export interface SessionReturns { session: SessionDocument; diff --git a/common/src/lib/schemas.ts b/common/src/lib/schemas.ts index 97ec34f96..ef68e2299 100644 --- a/common/src/lib/schemas.ts +++ b/common/src/lib/schemas.ts @@ -866,6 +866,9 @@ function PR_METRIC(metric: ConfScoreMetric): ValidSchemaValue { case "ENUM": return p.isIn(metric.values); + + case "NULLABLE_GRAPH": + return ["?number"]; } } diff --git a/common/src/types/documents.ts b/common/src/types/documents.ts index 233783e48..3d872cf6c 100644 --- a/common/src/types/documents.ts +++ b/common/src/types/documents.ts @@ -1,26 +1,26 @@ import type { ChartDocumentData, - Versions, Classes, + DerivedMetrics, Difficulties, - ConfOptionalMetrics as ConfOptionalMetrics, GPTString, GPTStringToGame, GPTStringToPlaytype, Game, Judgements, + OptionalMetrics, Playtype, Playtypes, Preferences, ProfileRatingAlgorithms, + ProvidedMetrics, ScoreMeta, ScoreRatingAlgorithms, SessionRatingAlgorithms, SongDocumentData, UserAuthLevels, + Versions, integer, - DerivedMetrics, - ProvidedMetrics, } from "../types"; import type { APIPermissions } from "./api"; import type { ImportTypes } from "./import-types"; @@ -417,7 +417,7 @@ export type QuestSubscriptionDocument = { export type ScoreData = DerivedMetrics[GPT] & ProvidedMetrics[GPT] & { judgements: Partial>; - optional: Partial; + optional: Partial; }; export interface ScoreDocument { diff --git a/common/src/utils/util.ts b/common/src/utils/util.ts index 8fa0998cd..de97a68b7 100644 --- a/common/src/utils/util.ts +++ b/common/src/utils/util.ts @@ -7,7 +7,7 @@ import type { Playtypes, SongDocument, } from "../types"; -import type { PrudenceSchema, ValidSchemaValue } from "prudence"; +import type { PrudenceError, ValidSchemaValue } from "prudence"; import type { AnyZodObject } from "zod"; export function FormatInt(v: number): string { @@ -43,7 +43,7 @@ export function FormatDifficulty(chart: ChartDocument, game: Game): string { // it's technically correct, but in the worst way, since this isn't // actually possible. // todo: come up with something better. - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access const shortDiff = gptConfig.difficulties.difficultyShorthand[ch.difficulty]; // gitadora should always use short diffs. they just look better. @@ -216,3 +216,17 @@ export function PrudenceZodShim(zodSchema: AnyZodObject): ValidSchemaValue { return res.error.message; }; } + +/** + * Formats a PrudenceError into something a little more readable. + * @param err - The prudence error to format. + * @param foreword - A description of what kind of error this was. Defaults to "Error". + */ +export function FormatPrError(err: PrudenceError, foreword = "Error"): string { + const receivedText = + typeof err.userVal === "object" && err.userVal !== null + ? "" + : ` | Received ${err.userVal} [${err.userVal === null ? "null" : typeof err.userVal}]`; + + return `${foreword}: ${err.keychain} | ${err.message}${receivedText}.`; +} diff --git a/database-seeds/scripts/rerunners/iidx/aix-output/parse-aix-json.ts b/database-seeds/scripts/rerunners/iidx/aix-output/parse-aix-json.ts index c07e42305..f7e3aa42f 100644 --- a/database-seeds/scripts/rerunners/iidx/aix-output/parse-aix-json.ts +++ b/database-seeds/scripts/rerunners/iidx/aix-output/parse-aix-json.ts @@ -1,6 +1,13 @@ import { readdirSync, readFileSync } from "fs"; import { join } from "path"; -import { ChartDocument, Difficulties, integer, Playtypes, SongDocument } from "tachi-common"; +import { + ChartDocument, + Difficulties, + GPTStrings, + integer, + Playtypes, + SongDocument, +} from "tachi-common"; import { CreateChartID, GetFreshScoreIDGenerator, MutateCollection } from "../../util"; interface AixChart { @@ -22,7 +29,7 @@ interface AixData { } function ConvertAixStuff(d: AixData, songID: integer) { - const searchTerms = []; + const searchTerms: Array = []; if (d.title !== d.title_ascii) { searchTerms.push(d.title_ascii); @@ -40,7 +47,7 @@ function ConvertAixStuff(d: AixData, songID: integer) { id: songID, }; - const charts = []; + const charts: Array> = []; for (const [diff, c] of Object.entries(d.charts)) { // wonderful ts oddity charts.push(ParseAixChart(d, c, diff as ChartStrings, songID)); @@ -76,27 +83,57 @@ function SplitAixDiff(diff: ChartStrings): { function ParseAixChart(d: AixData, c: AixChart, diff: ChartStrings, songID: integer) { const { difficulty, playtype } = SplitAixDiff(diff); - const chart: ChartDocument<"iidx:SP" | "iidx:DP"> = { - chartID: CreateChartID(), - data: { - notecount: c.note_count, - inGameID: d.entry_id, - "2dxtraSet": null, - bpiCoefficient: null, - hashSHA256: null, - kaidenAverage: null, - worldRecord: null, - }, - difficulty, - playtype, - isPrimary: true, - level: c.rating.toString(), - levelNum: c.rating, - rgcID: null, - songID, - tierlistInfo: {}, - versions: ["inf"], - }; + let chart: ChartDocument; + + if (playtype === "SP") { + const temp: ChartDocument<"iidx:SP"> = { + chartID: CreateChartID(), + data: { + notecount: c.note_count, + inGameID: d.entry_id, + "2dxtraSet": null, + bpiCoefficient: null, + hashSHA256: null, + kaidenAverage: null, + worldRecord: null, + exhcTier: null, + hcTier: null, + ncTier: null, + }, + difficulty, + playtype, + isPrimary: true, + level: c.rating.toString(), + levelNum: c.rating, + songID, + versions: ["INFINITAS"], + }; + + chart = temp; + } else { + const temp: ChartDocument<"iidx:DP"> = { + chartID: CreateChartID(), + data: { + notecount: c.note_count, + inGameID: d.entry_id, + "2dxtraSet": null, + bpiCoefficient: null, + hashSHA256: null, + kaidenAverage: null, + worldRecord: null, + dpTier: null, + }, + difficulty, + playtype, + isPrimary: true, + level: c.rating.toString(), + levelNum: c.rating, + songID, + versions: ["INFINITAS"], + }; + + chart = temp; + } return chart; } @@ -106,8 +143,8 @@ if (require.main === module) { const getSongID = GetFreshScoreIDGenerator("iidx"); - const newSongs = []; - const newCharts = []; + const newSongs: Array> = []; + const newCharts: Array> = []; for (const file of files) { if (file.endsWith(".json")) { const songID = getSongID(); diff --git a/database-seeds/scripts/rerunners/iidx/iidx-mdb-parse/merge-mdb.ts b/database-seeds/scripts/rerunners/iidx/iidx-mdb-parse/merge-mdb.ts index 6a2439b5d..4f34b55b6 100644 --- a/database-seeds/scripts/rerunners/iidx/iidx-mdb-parse/merge-mdb.ts +++ b/database-seeds/scripts/rerunners/iidx/iidx-mdb-parse/merge-mdb.ts @@ -3,7 +3,7 @@ import { ChartDocument, Difficulties, GetGamePTConfig, - GPTSupportedVersions, + Versions, integer, SongDocument, } from "tachi-common"; @@ -38,7 +38,7 @@ program program.parse(process.argv); const options = program.opts() as { - version: GPTSupportedVersions["iidx:SP"]; + version: Versions["iidx:SP"]; index: "0" | "1"; basedir: string; omni: boolean; diff --git a/server/src/external/mongo/db.ts b/server/src/external/mongo/db.ts index 3e739dde3..c7938f4f4 100644 --- a/server/src/external/mongo/db.ts +++ b/server/src/external/mongo/db.ts @@ -42,7 +42,7 @@ import type { TachiAPIClientDocument, UGPTSettings, UserGameStats, - UserGameStatsSnapshot, + UserGameStatsSnapshotDocument, UserSettings, KsHookSettingsDocument, ImportTrackerDocument as ImportTrackerDocument, @@ -161,7 +161,7 @@ const db = { tables: monkDB.get("tables"), "invite-locks": monkDB.get<{ userID: integer; locked: boolean }>("invite-locks"), "game-settings": monkDB.get("game-settings"), - "game-stats-snapshots": monkDB.get("game-stats-snapshots"), + "game-stats-snapshots": monkDB.get("game-stats-snapshots"), "user-settings": monkDB.get("user-settings"), "user-private-information": monkDB.get("user-private-information"), "api-clients": monkDB.get("api-clients"), diff --git a/server/src/lib/jobs/ugs-snapshot.ts b/server/src/lib/jobs/ugs-snapshot.ts index e0fcfdc38..8f13f11fd 100644 --- a/server/src/lib/jobs/ugs-snapshot.ts +++ b/server/src/lib/jobs/ugs-snapshot.ts @@ -2,7 +2,7 @@ import db from "external/mongo/db"; import CreateLogCtx from "lib/logger/logger"; import { GetMillisecondsSince } from "utils/misc"; import { GetAllRankings } from "utils/user"; -import type { UserGameStats, UserGameStatsSnapshot } from "tachi-common"; +import type { UserGameStats, UserGameStatsSnapshotDocument } from "tachi-common"; const logger = CreateLogCtx(__filename); @@ -10,7 +10,7 @@ const logger = CreateLogCtx(__filename); // nonsense happens. we'll have to see. const currentTime = new Date().setUTCHours(0, 0, 0, 0); -let batchWrite: Array = []; +let batchWrite: Array = []; // This code is intentionally *very* robust, and handles a lot of unanticipated failures // because if it breaks, we brick the database. @@ -48,7 +48,7 @@ export async function UGSSnapshot() { GetAllRankings(ugs), ]); - const ugsSnapshot: UserGameStatsSnapshot = { + const ugsSnapshot: UserGameStatsSnapshotDocument = { ...ugs, playcount, rankings, diff --git a/server/src/lib/jobs/update-bpi-data.ts b/server/src/lib/jobs/update-bpi-data.ts index 5231ab257..b1fd8d4f4 100644 --- a/server/src/lib/jobs/update-bpi-data.ts +++ b/server/src/lib/jobs/update-bpi-data.ts @@ -1,5 +1,4 @@ /* eslint-disable no-await-in-loop */ -import { VERSION_INFO } from "lib/constants/version"; import { PullDatabaseSeeds } from "lib/database-seeds/repo"; import CreateLogCtx from "lib/logger/logger"; import { RecalcAllScores } from "utils/calculations/recalc-scores"; @@ -7,7 +6,7 @@ import fetch from "utils/fetch"; import type { ChartDocument, Difficulties, - GPTSupportedVersions, + Versions, integer, Playtypes, SongDocument, @@ -82,7 +81,7 @@ export async function UpdatePoyashiData() { songID: integer, playtype: Playtypes["iidx"], diff: Difficulties["iidx:DP" | "iidx:SP"], - version: GPTSupportedVersions["iidx:DP" | "iidx:SP"] + version: Versions["iidx:DP" | "iidx:SP"] ) { for (const chart of iidxCharts) { if ( @@ -119,7 +118,7 @@ export async function UpdatePoyashiData() { } // current poyashi version is 29 - const tachiChart = FindChartWithPTDFVersion(tachiSong.id, playtype, diff, "29"); + const tachiChart = FindChartWithPTDFVersion(tachiSong.id, playtype, diff, "CastHour"); if (!tachiChart) { logger.warn( diff --git a/server/src/lib/jobs/update-dp-tiers.ts b/server/src/lib/jobs/update-dp-tiers.ts index 10b2612a5..b10a29495 100644 --- a/server/src/lib/jobs/update-dp-tiers.ts +++ b/server/src/lib/jobs/update-dp-tiers.ts @@ -1,8 +1,7 @@ /* eslint-disable no-await-in-loop */ import db from "external/mongo/db"; import { decode } from "html-entities"; -import { VERSION_INFO } from "lib/constants/version"; -import { BacksyncCollectionToBothBranches, PullDatabaseSeeds } from "lib/database-seeds/repo"; +import { BacksyncCollectionToBothBranches } from "lib/database-seeds/repo"; import CreateLogCtx from "lib/logger/logger"; import { parse } from "node-html-parser"; import { RecalcAllScores } from "utils/calculations/recalc-scores"; @@ -60,7 +59,7 @@ export async function UpdateDPTiers() { const result = await db.charts.iidx.update( { - versions: "29", + versions: "CastHour", playtype: "DP", songID: song.id, difficulty, diff --git a/server/src/lib/jobs/update-sp12-data.ts b/server/src/lib/jobs/update-sp12-data.ts index fac307114..1059a5eea 100644 --- a/server/src/lib/jobs/update-sp12-data.ts +++ b/server/src/lib/jobs/update-sp12-data.ts @@ -61,7 +61,7 @@ async function FetchSP12Data() { const updatedChartIDs: Array = []; for (const sh of rj.sheets) { - let chart: ChartDocument | null; + let chart: ChartDocument<"iidx:SP"> | null; try { chart = await HumanisedTitleLookup(sh.title); @@ -142,26 +142,26 @@ async function FetchSP12Data() { val = parseFloat(val.toFixed(2)); - let ktKey: keyof ChartDocument<"iidx:SP">["tierlistInfo"]; + let ktKey: "exhcTier" | "hcTier" | "ncTier"; if (key === "exh") { - ktKey = "kt-EXHC"; + ktKey = "exhcTier"; } else if (key === "hard") { - ktKey = "kt-HC"; + ktKey = "hcTier"; } else { - ktKey = "kt-NC"; + ktKey = "ncTier"; } // If EXH, just save the string version as 12.xx // Else, use the A/S+ thing that people are used to. const text = - ktKey === "kt-EXHC" + ktKey === "exhcTier" ? val.toFixed(2) : `12${stringVal.replace(/(個人差|地力)/u, "")}`; const idvDiff = stringVal.includes("個人差"); - const existingTlInfo = chart.tierlistInfo[ktKey]; + const existingTlInfo = chart.data[ktKey]; if ( existingTlInfo && @@ -180,7 +180,7 @@ async function FetchSP12Data() { }, { $set: { - [`tierlistInfo.${ktKey}`]: { + [`data.${ktKey}`]: { text, value: val, individualDifference: idvDiff, @@ -254,7 +254,7 @@ async function HumanisedTitleLookup(originalTitle: string) { ); } - return chart; + return chart as ChartDocument<"iidx:SP">; } if (require.main === module) { diff --git a/server/src/lib/orphan-queue/orphan-queue.ts b/server/src/lib/orphan-queue/orphan-queue.ts index 306e0f324..3d98722e8 100644 --- a/server/src/lib/orphan-queue/orphan-queue.ts +++ b/server/src/lib/orphan-queue/orphan-queue.ts @@ -116,12 +116,12 @@ export async function DeorphanIfInQueue( game: IDStringToGame[I], orphanMatchCriteria: FilterQuery> ): Promise | null> { - const orphanChart = (await db["orphan-chart-queue"].findOne( + const orphanChart = await db["orphan-chart-queue"].findOne( { idString, ...orphanMatchCriteria }, { projectID: true, } - )) as WithID> | null; + ); if (!orphanChart) { return null; diff --git a/server/src/lib/score-import/framework/user-game-stats/rating.ts b/server/src/lib/score-import/framework/user-game-stats/rating.ts index 34b597f1e..68df37150 100644 --- a/server/src/lib/score-import/framework/user-game-stats/rating.ts +++ b/server/src/lib/score-import/framework/user-game-stats/rating.ts @@ -2,7 +2,7 @@ import db from "external/mongo/db"; import type { KtLogger } from "lib/logger/logger"; import type { Game, - GPTSupportedVersions, + Versions, GPTString, integer, PBScoreDocument, @@ -456,7 +456,7 @@ async function GetBestJubilityOnSongs( return r.map((e) => e.doc); } -const CURRENT_JUBEAT_HOT_VERSION: GPTSupportedVersions["jubeat:Single"] = "festo"; +const CURRENT_JUBEAT_HOT_VERSION: Versions["jubeat:Single"] = "festo"; export async function GetPBsForJubility(userID: integer) { const hotSongs = await db.songs.jubeat.find( diff --git a/server/src/lib/score-import/import-types/common/api-cg/museca/converter.ts b/server/src/lib/score-import/import-types/common/api-cg/museca/converter.ts index 17a0381d5..00494cd31 100644 --- a/server/src/lib/score-import/import-types/common/api-cg/museca/converter.ts +++ b/server/src/lib/score-import/import-types/common/api-cg/museca/converter.ts @@ -14,7 +14,7 @@ import { FindSongOnID } from "utils/queries/songs"; import type { ConverterFunction } from "../../types"; import type { CGContext, CGMusecaScore } from "../types"; import type { DryScore } from "lib/score-import/framework/common/types"; -import type { Difficulties, GPTSupportedVersions } from "tachi-common"; +import type { Difficulties, Versions } from "tachi-common"; export const ConverterAPICGMuseca: ConverterFunction = async ( data, @@ -94,7 +94,7 @@ function ConvertDifficulty(diff: number): Difficulties["museca:Single"] { throw new InvalidScoreFailure(`Invalid difficulty of ${diff} - Could not convert.`); } -function ConvertVersion(ver: number): GPTSupportedVersions["museca:Single"] { +function ConvertVersion(ver: number): Versions["museca:Single"] { switch (ver) { case 1: return "1.5-b"; diff --git a/server/src/lib/score-import/import-types/common/api-cg/popn/converter.ts b/server/src/lib/score-import/import-types/common/api-cg/popn/converter.ts index 337a7f43f..b4d2a7ea7 100644 --- a/server/src/lib/score-import/import-types/common/api-cg/popn/converter.ts +++ b/server/src/lib/score-import/import-types/common/api-cg/popn/converter.ts @@ -13,13 +13,7 @@ import { FindSongOnID } from "utils/queries/songs"; import type { ConverterFunction } from "../../types"; import type { CGContext, CGPopnScore } from "../types"; import type { DryScore } from "lib/score-import/framework/common/types"; -import type { - Difficulties, - GPTSupportedVersions, - HitMetaLookup, - Lamps, - integer, -} from "tachi-common"; +import type { Difficulties, Versions, HitMetaLookup, Lamps, integer } from "tachi-common"; export const ConverterAPICGPopn: ConverterFunction = async ( data, @@ -112,7 +106,7 @@ function ConvertDifficulty(diff: number): Difficulties["popn:9B"] { throw new InvalidScoreFailure(`Invalid difficulty of ${diff} - Could not convert.`); } -function ConvertVersion(ver: number): GPTSupportedVersions["popn:9B"] { +function ConvertVersion(ver: number): Versions["popn:9B"] { switch (ver) { case 26: return "kaimei"; diff --git a/server/src/lib/score-import/import-types/common/api-cg/sdvx/converter.ts b/server/src/lib/score-import/import-types/common/api-cg/sdvx/converter.ts index 6569de716..d3baf0597 100644 --- a/server/src/lib/score-import/import-types/common/api-cg/sdvx/converter.ts +++ b/server/src/lib/score-import/import-types/common/api-cg/sdvx/converter.ts @@ -13,7 +13,7 @@ import { FindSongOnID } from "utils/queries/songs"; import type { ConverterFunction } from "../../types"; import type { CGContext, CGSDVXScore } from "../types"; import type { DryScore } from "lib/score-import/framework/common/types"; -import type { GPTSupportedVersions, Lamps } from "tachi-common"; +import type { Versions, Lamps } from "tachi-common"; export const ConverterAPICGSDVX: ConverterFunction = async ( data, @@ -91,7 +91,7 @@ function ConvertDifficulty(diff: number) { throw new InvalidScoreFailure(`Invalid difficulty of ${diff} - Could not convert.`); } -function ConvertVersion(ver: number): GPTSupportedVersions["sdvx:Single"] { +function ConvertVersion(ver: number): Versions["sdvx:Single"] { switch (ver) { case 1: return "booth"; diff --git a/server/src/lib/score-import/import-types/common/api-kai/iidx/converter.ts b/server/src/lib/score-import/import-types/common/api-kai/iidx/converter.ts index 6ee9a7b47..f17064ef3 100644 --- a/server/src/lib/score-import/import-types/common/api-kai/iidx/converter.ts +++ b/server/src/lib/score-import/import-types/common/api-kai/iidx/converter.ts @@ -29,7 +29,9 @@ const PR_KAI_IIDX_SCORE = { timestamp: "string", }; -function ResolveKaiLamp(lamp: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7): GetEnumValue<"iidx:DP" | "iidx:SP", "lamp"> { +function ResolveKaiLamp( + lamp: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 +): GetEnumValue<"iidx:DP" | "iidx:SP", "lamp"> { switch (lamp) { case 0: return "NO PLAY"; diff --git a/server/src/lib/score-import/import-types/common/batch-manual/converter.ts b/server/src/lib/score-import/import-types/common/batch-manual/converter.ts index 5837a2ced..a6e931801 100644 --- a/server/src/lib/score-import/import-types/common/batch-manual/converter.ts +++ b/server/src/lib/score-import/import-types/common/batch-manual/converter.ts @@ -28,7 +28,7 @@ import type { BatchManualScore, ChartDocument, Difficulties, - GPTSupportedVersions, + Versions, Grades, GPTString, ImportTypes, @@ -315,7 +315,7 @@ export async function ResolveMatchTypeToTachiData( chart = await FindSDVXChartOnInGameIDVersion( identifier, diff, - context.version as GPTSupportedVersions["sdvx:Single"] + context.version as Versions["sdvx:Single"] ); } else { chart = await FindSDVXChartOnInGameID(identifier, diff); diff --git a/server/src/lib/score-import/import-types/common/batch-manual/types.ts b/server/src/lib/score-import/import-types/common/batch-manual/types.ts index 6c2e6f14d..f13c29004 100644 --- a/server/src/lib/score-import/import-types/common/batch-manual/types.ts +++ b/server/src/lib/score-import/import-types/common/batch-manual/types.ts @@ -1,8 +1,8 @@ -import type { Game, GPTSupportedVersions, GPTString, Playtype } from "tachi-common"; +import type { Game, Versions, GPTString, Playtype } from "tachi-common"; export interface BatchManualContext { game: Game; playtype: Playtype; service: string; - version: GPTSupportedVersions[GPTString] | null; + version: Versions[GPTString] | null; } diff --git a/server/src/lib/score-import/import-types/common/eamusement-iidx-csv/parser.ts b/server/src/lib/score-import/import-types/common/eamusement-iidx-csv/parser.ts index 1f9412db9..0938fbbca 100644 --- a/server/src/lib/score-import/import-types/common/eamusement-iidx-csv/parser.ts +++ b/server/src/lib/score-import/import-types/common/eamusement-iidx-csv/parser.ts @@ -5,7 +5,7 @@ import { CSVParseError, NaiveCSVParse } from "utils/naive-csv-parser"; import type { ParserFunctionReturns } from "../types"; import type { EamusementScoreData, IIDXEamusementCSVContext, IIDXEamusementCSVData } from "./types"; import type { KtLogger } from "lib/logger/logger"; -import type { integer, GPTSupportedVersions, Playtypes } from "tachi-common"; +import type { integer, Versions, Playtypes } from "tachi-common"; export enum EAM_VERSION_NAMES { "1st&substream" = 1, @@ -178,7 +178,7 @@ export function IIDXCSVParse(csvBuffer: Buffer, playtype: Playtypes["iidx"], log return { iterableData, - version: gameVersion.toString() as GPTSupportedVersions["iidx:DP" | "iidx:SP"], + version: gameVersion.toString() as Versions["iidx:DP" | "iidx:SP"], hasBeginnerAndLegg, }; } diff --git a/server/src/lib/score-import/import-types/common/eamusement-iidx-csv/types.ts b/server/src/lib/score-import/import-types/common/eamusement-iidx-csv/types.ts index 661dca79c..86b188f38 100644 --- a/server/src/lib/score-import/import-types/common/eamusement-iidx-csv/types.ts +++ b/server/src/lib/score-import/import-types/common/eamusement-iidx-csv/types.ts @@ -1,4 +1,4 @@ -import type { GPTSupportedVersions } from "tachi-common"; +import type { Versions } from "tachi-common"; export interface EamusementScoreData { difficulty: "ANOTHER" | "BEGINNER" | "HYPER" | "LEGGENDARIA" | "NORMAL"; @@ -30,7 +30,7 @@ export type RawIIDXEamusementCSVData = BaseProps & export interface IIDXEamusementCSVContext { playtype: "DP" | "SP"; - importVersion: GPTSupportedVersions["iidx:DP" | "iidx:SP"]; + importVersion: Versions["iidx:DP" | "iidx:SP"]; hasBeginnerAndLegg: boolean; service: string; } 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 bb6877052..a330c6de6 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 @@ -3,16 +3,13 @@ import { SongOrChartNotFoundFailure, SkipScoreFailure, } from "../../../framework/common/converter-failures"; -import { - GenericGetGradeAndPercent, - ParseDateFromString, -} from "../../../framework/common/score-utils"; +import { ParseDateFromString } from "../../../framework/common/score-utils"; import { FindChartWithPTDFVersion } from "utils/queries/charts"; import { FindSongOnTitleInsensitive } from "utils/queries/songs"; import type { DryScore } from "../../../framework/common/types"; import type { ConverterFunction } from "../../common/types"; import type { S3Score } from "./types"; -import type { Difficulties, GPTSupportedVersions, Lamps, Playtypes } from "tachi-common"; +import type { Difficulties, Playtypes, Versions } from "tachi-common"; import type { EmptyObject } from "utils/types"; export function ParseDifficulty(diff: S3Score["diff"]): { @@ -71,23 +68,23 @@ export function ResolveS3Lamp(data: S3Score): GetEnumValue<"iidx:DP" | "iidx:SP" } } -const S3_VERSION_CONV: Record = { - "3rd": "3-cs", - "4th": "4-cs", - "5th": "5-cs", - "6th": "6-cs", - "7th": "7-cs", - "8th": "8-cs", - "9th": "9-cs", - "10th": "10-cs", - red: "11-cs", - hs: "12-cs", - dd: "13-cs", - gold: "14-cs", - djt: "15-cs", - emp: "16-cs", - pb: "16-cs", - us: "bmus", +const S3_VERSION_CONV: Record = { + "3rd": "3rd Style CS", + "4th": "4th Style CS", + "5th": "5th Style CS", + "6th": "6th Style CS", + "7th": "7th Style CS", + "8th": "8th Style CS", + "9th": "9th Style CS", + "10th": "10th Style CS", + red: "IIDX RED CS", + hs: "HAPPY SKY CS", + dd: "DISTORTED CS", + gold: "GOLD CS", + djt: "DJ TROOPERS CS", + emp: "EMPRESS CS", + pb: "EMPRESS CS", + us: "BEATMANIA US", }; function ConvertVersion(joinedStyles: string) { @@ -139,8 +136,6 @@ export const ConvertFileS3: ConverterFunction = async ( ); } - const { percent, grade } = GenericGetGradeAndPercent("iidx", data.exscore, chart); - const lamp = ResolveS3Lamp(data); const timeAchieved = ParseDateFromString(data.date); @@ -163,8 +158,6 @@ export const ConvertFileS3: ConverterFunction = async ( importType: "file/solid-state-squad", service: "Solid State Squad", scoreData: { - percent, - grade, score: data.exscore, lamp, judgements, diff --git a/server/src/lib/score-import/import-types/file/wacca-mypage-scraper/converter.ts b/server/src/lib/score-import/import-types/file/wacca-mypage-scraper/converter.ts index 1998dc8ff..5b85737ba 100644 --- a/server/src/lib/score-import/import-types/file/wacca-mypage-scraper/converter.ts +++ b/server/src/lib/score-import/import-types/file/wacca-mypage-scraper/converter.ts @@ -1,15 +1,14 @@ import { - InternalFailure, InvalidScoreFailure, SongOrChartNotFoundFailure, } from "lib/score-import/framework/common/converter-failures"; -import { GenericGetGradeAndPercent } from "lib/score-import/framework/common/score-utils"; import { FindChartWithPTDF } from "utils/queries/charts"; import { FindSongOnTitle } from "utils/queries/songs"; import type { ConverterFunction } from "../../common/types"; import type { MyPageRecordsParsedPB } from "./types"; import type { DryScore } from "lib/score-import/framework/common/types"; -import type { Difficulties, Lamps } from "tachi-common"; +import type { Difficulties } from "tachi-common"; +import type { GetEnumValue } from "tachi-common/types/metrics"; import type { EmptyObject } from "utils/types"; const DIFFICULTIES: Array = ["NORMAL", "HARD", "EXPERT", "INFERNO"]; @@ -41,7 +40,9 @@ const ConvertMyPageScraperRecordsCSV: ConverterFunction< const difficulty = DIFFICULTIES[data.diffIndex]; if (difficulty === undefined) { - throw new InternalFailure(`We somehow got an invalid difficulty index ${data.diffIndex}.`); + throw new InvalidScoreFailure( + `Invalid difficulty index of ${data.diffIndex}. This corresponds to some unknown difficulty. Invalid input?` + ); } const humanisedChartTitle = `${song.title} [${difficulty}]`; @@ -78,18 +79,16 @@ const ConvertMyPageScraperRecordsCSV: ConverterFunction< if (data.score === 1_000_000 && lamp !== "ALL MARVELOUS") { throw new InvalidScoreFailure( - `MASTER score of ${data.score}, but lamp ${lamp} is not ALL MARVELOUS.` + `Got a score of ${data.score}, but lamp ${lamp} is not ALL MARVELOUS.` ); } if (lamp === "ALL MARVELOUS" && data.score !== 1_000_000) { throw new InvalidScoreFailure( - `AM lamp ${lamp}, but score is ${data.score}, not 1,000,000.` + `Got a lamp of '${lamp}', but score is ${data.score}, not 1,000,000.` ); } - const { percent, grade } = GenericGetGradeAndPercent("wacca", data.score, chart); - const dryScore: DryScore<"wacca:Single"> = { service: "mypage-scraper", game: "wacca", @@ -102,17 +101,11 @@ const ConvertMyPageScraperRecordsCSV: ConverterFunction< scoreData: { score: data.score, lamp, - percent, - grade, judgements: {}, optional: {}, }, }; - logger.verbose( - `Returning dryscore with ${dryScore.scoreData.score} for ${humanisedChartTitle}` - ); - return { chart, song, dryScore }; }; diff --git a/server/src/lib/score-import/import-types/file/wacca-mypage-scraper/parser.ts b/server/src/lib/score-import/import-types/file/wacca-mypage-scraper/parser.ts index bdf42c429..51771f32f 100644 --- a/server/src/lib/score-import/import-types/file/wacca-mypage-scraper/parser.ts +++ b/server/src/lib/score-import/import-types/file/wacca-mypage-scraper/parser.ts @@ -54,6 +54,7 @@ export function ParseMyPageScraperRecordsCSV( try { rawCSVRecords = parse(fileData.buffer, { columns: true }) as Array; } catch (err) { + // eslint-disable-next-line cadence/no-instanceof if (err instanceof CSVError) { throw new ScoreImportFatalError(400, `Failed to parse CSV: ${err.message}`); } @@ -124,6 +125,7 @@ export function ParseMyPageScraperPlayerCSV( try { csvRecords = parse(fileData.buffer, { columns: true }) as Array>; } catch (err) { + // eslint-disable-next-line cadence/no-instanceof if (err instanceof CSVError) { throw new ScoreImportFatalError(400, `Failed to parse CSV: ${err.message}`); } diff --git a/server/src/lib/score-import/import-types/ir/barbatos/types.ts b/server/src/lib/score-import/import-types/ir/barbatos/types.ts index 3c1aa64c3..1e304aece 100644 --- a/server/src/lib/score-import/import-types/ir/barbatos/types.ts +++ b/server/src/lib/score-import/import-types/ir/barbatos/types.ts @@ -1,4 +1,4 @@ -import type { GPTSupportedVersions, integer } from "tachi-common"; +import type { Versions, integer } from "tachi-common"; export interface BarbatosScore { difficulty: 0 | 1 | 2 | 3 | 4; @@ -52,5 +52,5 @@ export interface BarbatosSDVX6Score { export interface BarbatosContext { timeReceived: number; - version: GPTSupportedVersions["sdvx:Single"]; + version: Versions["sdvx:Single"]; } diff --git a/server/src/lib/score-import/import-types/ir/fervidex-static/types.ts b/server/src/lib/score-import/import-types/ir/fervidex-static/types.ts index 8c8fbae66..daaadf156 100644 --- a/server/src/lib/score-import/import-types/ir/fervidex-static/types.ts +++ b/server/src/lib/score-import/import-types/ir/fervidex-static/types.ts @@ -1,4 +1,4 @@ -import type { GPTSupportedVersions, integer } from "tachi-common"; +import type { Versions, integer } from "tachi-common"; export interface FervidexStaticScore { clear_type: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7; @@ -11,7 +11,7 @@ export interface FervidexStaticScore { } export interface FervidexStaticContext { - version: GPTSupportedVersions["iidx:DP" | "iidx:SP"]; + version: Versions["iidx:DP" | "iidx:SP"]; } export interface FervidexStaticHeaders { diff --git a/server/src/lib/score-import/import-types/ir/fervidex/parser.ts b/server/src/lib/score-import/import-types/ir/fervidex/parser.ts index a5fde3acb..475327af2 100644 --- a/server/src/lib/score-import/import-types/ir/fervidex/parser.ts +++ b/server/src/lib/score-import/import-types/ir/fervidex/parser.ts @@ -11,15 +11,14 @@ import { REV_NORMAL, REV_OMNIMIX, } from "lib/constants/ea3id"; -import { CreateScoreID } from "lib/score-import/framework/score-importing/score-id"; import { p } from "prudence"; import { ParseEA3SoftID } from "utils/ea3id"; import { FormatPrError, optNull } from "utils/prudence"; import type { ParserFunctionReturns } from "../../common/types"; -import type { FerHeaders as FervidexHeaders, FervidexContext, FervidexScore } from "./types"; +import type { FervidexContext, FerHeaders as FervidexHeaders, FervidexScore } from "./types"; import type { KtLogger } from "lib/logger/logger"; import type { PrudenceSchema, ValidSchemaValue } from "prudence"; -import type { GPTSupportedVersions, integer } from "tachi-common"; +import type { Versions, integer } from "tachi-common"; const PR_FERVIDEX: PrudenceSchema = { chart: p.isIn("spb", "spn", "dpn", "sph", "dph", "spa", "dpa", "spl", "dpl"), @@ -82,7 +81,7 @@ const PR_FERVIDEX: PrudenceSchema = { export function SoftwareIDToVersion( model: string, logger: KtLogger -): GPTSupportedVersions["iidx:DP" | "iidx:SP"] { +): Versions["iidx:DP" | "iidx:SP"] { try { const data = ParseEA3SoftID(model); diff --git a/server/src/lib/score-import/import-types/ir/fervidex/types.ts b/server/src/lib/score-import/import-types/ir/fervidex/types.ts index 7f0913796..aaa04833c 100644 --- a/server/src/lib/score-import/import-types/ir/fervidex/types.ts +++ b/server/src/lib/score-import/import-types/ir/fervidex/types.ts @@ -1,4 +1,4 @@ -import type { GPTSupportedVersions, integer } from "tachi-common"; +import type { Versions, integer } from "tachi-common"; export interface FervidexScore { chart: `${"dp" | "sp"}${"a" | "b" | "h" | "l" | "n"}`; @@ -65,7 +65,7 @@ export interface FervidexScore { } export interface FervidexContext { - version: GPTSupportedVersions["iidx:DP" | "iidx:SP"]; + version: Versions["iidx:DP" | "iidx:SP"]; timeReceived: number; userID: integer; } diff --git a/server/src/server/router/api/v1/games/_game/_playtype/charts/router.ts b/server/src/server/router/api/v1/games/_game/_playtype/charts/router.ts index aa569f1a6..30d382f3f 100644 --- a/server/src/server/router/api/v1/games/_game/_playtype/charts/router.ts +++ b/server/src/server/router/api/v1/games/_game/_playtype/charts/router.ts @@ -92,11 +92,11 @@ router.get("/", async (req, res) => { (e) => (e as ChartDocument<"iidx:DP" | "iidx:SP">).data["2dxtraSet"] === null ); } else { - const iidxSettings = (await db["game-settings"].findOne({ + const iidxSettings = await db["game-settings"].findOne({ userID: req[SYMBOL_TACHI_API_AUTH].userID, game, playtype, - })) as UGPTSettings<"iidx:DP" | "iidx:SP"> | null; + }); if (!iidxSettings || !iidxSettings.preferences.gameSpecific.display2DXTra) { charts = charts.filter( diff --git a/server/src/server/router/api/v1/users/_userID/games/_game/_playtype/router.ts b/server/src/server/router/api/v1/users/_userID/games/_game/_playtype/router.ts index b6ca4ec07..1fc495026 100644 --- a/server/src/server/router/api/v1/users/_userID/games/_game/_playtype/router.ts +++ b/server/src/server/router/api/v1/users/_userID/games/_game/_playtype/router.ts @@ -30,7 +30,7 @@ import { GetUsersRankingAndOutOf, GetUsersWithIDs, } from "utils/user"; -import type { integer, PBScoreDocument, UserGameStatsSnapshot } from "tachi-common"; +import type { integer, PBScoreDocument, UserGameStatsSnapshotDocument } from "tachi-common"; const logger = CreateLogCtx(__filename); @@ -155,17 +155,18 @@ router.get( playtype: 0, }, } - )) as Array>; + )) as Array>; - const currentSnapshot: Omit = { - classes: stats.classes, - ratings: stats.ratings, + const currentSnapshot: Omit = + { + classes: stats.classes, + ratings: stats.ratings, - // lazy, should probably be this midnight - timestamp: Date.now(), - playcount: await GetUGPTPlaycount(user.id, game, playtype), - rankings: await GetAllRankings(stats), - }; + // lazy, should probably be this midnight + timestamp: Date.now(), + playcount: await GetUGPTPlaycount(user.id, game, playtype), + rankings: await GetAllRankings(stats), + }; return res.status(200).json({ success: true, diff --git a/server/src/server/router/api/v1/users/_userID/games/_game/_playtype/settings/router.test.ts b/server/src/server/router/api/v1/users/_userID/games/_game/_playtype/settings/router.test.ts index eff9a072b..80dcafcff 100644 --- a/server/src/server/router/api/v1/users/_userID/games/_game/_playtype/settings/router.test.ts +++ b/server/src/server/router/api/v1/users/_userID/games/_game/_playtype/settings/router.test.ts @@ -201,11 +201,11 @@ t.test("PATCH /api/v1/users/:userID/games/:game/:playtype/settings", (t) => { "Should only update the mutated properties." ); - const data = (await db["game-settings"].findOne({ + const data = await db["game-settings"].findOne({ userID: 1, game: "iidx", playtype: "SP", - })) as UGPTSettings<"iidx:DP" | "iidx:SP"> | null; + }); t.equal(data?.preferences.gameSpecific.bpiTarget, target); diff --git a/server/src/server/router/ir/beatoraja/charts/_chartSHA256/convert-scores.ts b/server/src/server/router/ir/beatoraja/charts/_chartSHA256/convert-scores.ts index b0b006c83..726200fb4 100644 --- a/server/src/server/router/ir/beatoraja/charts/_chartSHA256/convert-scores.ts +++ b/server/src/server/router/ir/beatoraja/charts/_chartSHA256/convert-scores.ts @@ -57,7 +57,7 @@ export function TachiScoreDataToBeatorajaFormat( sha256, player: username, playcount, - clear: LAMP_TO_BEATORAJA[scoreData.lampIndex] ?? 0, + clear: LAMP_TO_BEATORAJA[scoreData.lamp.index] ?? 0, date: pbScore.timeAchieved ?? 0, maxcombo: scoreData.optional.maxCombo ?? 0, gauge: scoreData.optional.gauge ?? 0, diff --git a/server/src/server/router/ir/usc/_playtype/usc.ts b/server/src/server/router/ir/usc/_playtype/usc.ts index 0e8ef536b..69956728a 100644 --- a/server/src/server/router/ir/usc/_playtype/usc.ts +++ b/server/src/server/router/ir/usc/_playtype/usc.ts @@ -4,12 +4,19 @@ import CreateLogCtx from "lib/logger/logger"; import { MStoS } from "utils/misc"; import { GetPBOnChart, GetServerRecordOnChart } from "utils/scores"; import type { USCServerScore } from "./types"; -import type { ChartDocument, integer, PBScoreDocument, ScoreDocument } from "tachi-common"; +import type { + ChartDocument, + GPTStrings, + integer, + PBScoreDocument, + ScoreDocument, +} from "tachi-common"; +import type { GetEnumValue } from "tachi-common/types/metrics"; const logger = CreateLogCtx(__filename); export const TACHI_LAMP_TO_USC: Record< - PBScoreDocument<"usc:Controller" | "usc:Keyboard">["scoreData"]["lamp"], + GetEnumValue, USCServerScore["lamp"] > = { // we don't do NO PLAY, so its not handled. diff --git a/server/src/utils/misc.ts b/server/src/utils/misc.ts index aeda714e1..a3b7a1697 100644 --- a/server/src/utils/misc.ts +++ b/server/src/utils/misc.ts @@ -6,14 +6,7 @@ import { exec } from "child_process"; import crypto from "crypto"; import { URL } from "url"; import type { KtLogger } from "lib/logger/logger"; -import type { - Game, - GamePTConfig, - integer, - Playtype, - GPTSupportedVersions, - GPTString, -} from "tachi-common"; +import type { Game, GamePTConfig, integer, Playtype, Versions, GPTString } from "tachi-common"; // https://github.com/sindresorhus/escape-string-regexp/blob/main/index.js // the developer of this has migrated everything to Force ES6 style modules, @@ -329,7 +322,7 @@ export function StringIsGameVersion( game: Game, playtype: Playtype, version: string -): version is GPTSupportedVersions[GPTString] { +): version is Versions[GPTString] { const gptConfig = GetGamePTConfig(game, playtype); // @ts-expect-error yes, we know! diff --git a/server/src/utils/queries/charts.ts b/server/src/utils/queries/charts.ts index f9b73bf4d..4acaa5e76 100644 --- a/server/src/utils/queries/charts.ts +++ b/server/src/utils/queries/charts.ts @@ -4,7 +4,7 @@ import type { ChartDocument, Difficulties, Game, - GPTSupportedVersions, + Versions, GPTString, integer, Playtype, @@ -41,13 +41,7 @@ export function FindChartWithPTDFVersion< G extends Game = Game, P extends Playtypes[G] = Playtypes[G], I extends GPTString = GPTString ->( - game: G, - songID: integer, - playtype: P, - difficulty: Difficulties[I], - version: GPTSupportedVersions[I] -) { +>(game: G, songID: integer, playtype: P, difficulty: Difficulties[I], version: Versions[I]) { return db.charts[game].findOne({ songID, playtype, @@ -118,7 +112,7 @@ export function FindIIDXChartOnInGameIDVersion( inGameID: number, playtype: Playtype, difficulty: Difficulties[GPTString], - version: GPTSupportedVersions[GPTString] + version: Versions[GPTString] ) { return db.charts.iidx.findOne({ "data.inGameID": inGameID, @@ -137,7 +131,7 @@ export function FindChartOnInGameIDVersion( inGameID: number, playtype: Playtype, difficulty: Difficulties[I], - version: GPTSupportedVersions[I] + version: Versions[I] ) { return db.charts[game].findOne({ "data.inGameID": inGameID, @@ -181,7 +175,7 @@ export function FindSDVXChartOnInGameID( export function FindSDVXChartOnInGameIDVersion( inGameID: number, difficulty: Difficulties["sdvx:Single"] | "ANY_INF", - version: GPTSupportedVersions["sdvx:Single"] + version: Versions["sdvx:Single"] ) { const diffQuery = difficulty === "ANY_INF" @@ -198,7 +192,7 @@ export function FindSDVXChartOnInGameIDVersion( export function FindSDVXChartOnDFVersion( songID: integer, difficulty: Difficulties["sdvx:Single"] | "ANY_INF", - version: GPTSupportedVersions["sdvx:Single"] + version: Versions["sdvx:Single"] ) { const diffQuery = difficulty === "ANY_INF" diff --git a/server/src/utils/queries/stats.ts b/server/src/utils/queries/stats.ts index 9987ed901..91b64fd9f 100644 --- a/server/src/utils/queries/stats.ts +++ b/server/src/utils/queries/stats.ts @@ -1,14 +1,14 @@ import db from "external/mongo/db"; import { ONE_HOUR } from "lib/constants/time"; import NodeCache from "node-cache"; -import type { Game, gameClasses, GPTString, integer, Playtype } from "tachi-common"; +import type { Classes, Game, GPTString, integer, Playtype } from "tachi-common"; const classDistCache = new NodeCache(); export async function GetClassDistribution( game: Game, playtype: Playtype, - className: gameClasses.GameClassSets[GPTString] + className: Classes[GPTString] ) { const cacheKey = `${game}:${playtype}:${className}`; const cache = classDistCache.get>(cacheKey);