checkpoint: 14

This commit is contained in:
zkldi
2023-01-19 16:39:31 +00:00
parent a3208f3ce5
commit 7c3650dd26
36 changed files with 203 additions and 173 deletions
+2 -2
View File
@@ -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<UserGameStatsSnapshot, "userID" | "game" | "playtype">[];
export type UGPTHistory = Omit<UserGameStatsSnapshotDocument, "userID" | "game" | "playtype">[];
export interface SessionReturns<I extends GPTString = GPTString> {
session: SessionDocument;
+3
View File
@@ -866,6 +866,9 @@ function PR_METRIC(metric: ConfScoreMetric): ValidSchemaValue {
case "ENUM":
return p.isIn(metric.values);
case "NULLABLE_GRAPH":
return ["?number"];
}
}
+5 -5
View File
@@ -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<GPT extends GPTString = GPTString> = DerivedMetrics[GPT] &
ProvidedMetrics[GPT] & {
judgements: Partial<Record<Judgements[GPT], integer | null>>;
optional: Partial<ConfOptionalMetrics[GPT]>;
optional: Partial<OptionalMetrics[GPT]>;
};
export interface ScoreDocument<GPT extends GPTString = GPTString> {
+16 -2
View File
@@ -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}.`;
}
@@ -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<string> = [];
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<ChartDocument<GPTStrings["iidx"]>> = [];
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<GPTStrings["iidx"]>;
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<SongDocument<"iidx">> = [];
const newCharts: Array<ChartDocument<GPTStrings["iidx"]>> = [];
for (const file of files) {
if (file.endsWith(".json")) {
const songID = getSongID();
@@ -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;
+2 -2
View File
@@ -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<TableDocument>("tables"),
"invite-locks": monkDB.get<{ userID: integer; locked: boolean }>("invite-locks"),
"game-settings": monkDB.get<UGPTSettings>("game-settings"),
"game-stats-snapshots": monkDB.get<UserGameStatsSnapshot>("game-stats-snapshots"),
"game-stats-snapshots": monkDB.get<UserGameStatsSnapshotDocument>("game-stats-snapshots"),
"user-settings": monkDB.get<UserSettings>("user-settings"),
"user-private-information": monkDB.get<PrivateUserInfoDocument>("user-private-information"),
"api-clients": monkDB.get<TachiAPIClientDocument>("api-clients"),
+3 -3
View File
@@ -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<UserGameStatsSnapshot> = [];
let batchWrite: Array<UserGameStatsSnapshotDocument> = [];
// 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,
+3 -4
View File
@@ -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(
+2 -3
View File
@@ -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,
+9 -9
View File
@@ -61,7 +61,7 @@ async function FetchSP12Data() {
const updatedChartIDs: Array<string> = [];
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) {
+2 -2
View File
@@ -116,12 +116,12 @@ export async function DeorphanIfInQueue<I extends GPTString>(
game: IDStringToGame[I],
orphanMatchCriteria: FilterQuery<OrphanChart<I>>
): Promise<ChartDocument<I> | null> {
const orphanChart = (await db["orphan-chart-queue"].findOne(
const orphanChart = await db["orphan-chart-queue"].findOne(
{ idString, ...orphanMatchCriteria },
{
projectID: true,
}
)) as WithID<OrphanChart<I>> | null;
);
if (!orphanChart) {
return null;
@@ -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(
@@ -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<CGMusecaScore, CGContext> = 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";
@@ -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<CGPopnScore, CGContext> = 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";
@@ -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<CGSDVXScore, CGContext> = 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";
@@ -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";
@@ -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);
@@ -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;
}
@@ -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,
};
}
@@ -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;
}
@@ -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<string, GPTSupportedVersions["iidx:SP"]> = {
"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<string, Versions["iidx:SP"]> = {
"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<S3Score, EmptyObject> = 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<S3Score, EmptyObject> = async (
importType: "file/solid-state-squad",
service: "Solid State Squad",
scoreData: {
percent,
grade,
score: data.exscore,
lamp,
judgements,
@@ -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<Difficulties["wacca:Single"]> = ["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 };
};
@@ -54,6 +54,7 @@ export function ParseMyPageScraperRecordsCSV(
try {
rawCSVRecords = parse(fileData.buffer, { columns: true }) as Array<unknown>;
} 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<Record<string, string>>;
} catch (err) {
// eslint-disable-next-line cadence/no-instanceof
if (err instanceof CSVError) {
throw new ScoreImportFatalError(400, `Failed to parse CSV: ${err.message}`);
}
@@ -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"];
}
@@ -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 {
@@ -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);
@@ -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;
}
@@ -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(
@@ -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<Omit<UserGameStatsSnapshot, "game" | "playtype" | "userID">>;
)) as Array<Omit<UserGameStatsSnapshotDocument, "game" | "playtype" | "userID">>;
const currentSnapshot: Omit<UserGameStatsSnapshot, "game" | "playtype" | "userID"> = {
classes: stats.classes,
ratings: stats.ratings,
const currentSnapshot: Omit<UserGameStatsSnapshotDocument, "game" | "playtype" | "userID"> =
{
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,
@@ -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);
@@ -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,
@@ -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<GPTStrings["usc"], "lamp">,
USCServerScore["lamp"]
> = {
// we don't do NO PLAY, so its not handled.
+2 -9
View File
@@ -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!
+6 -12
View File
@@ -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<I extends GPTString = GPTString>(
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"
+2 -2
View File
@@ -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<Record<string, integer>>(cacheKey);