Add GSM and Versioning support.

This commit is contained in:
zkldi
2021-05-13 22:58:07 +01:00
parent 262ed6d7e4
commit 0909fad7bc
6 changed files with 105 additions and 13 deletions
+3 -3
View File
@@ -60,7 +60,7 @@ dependencies:
express-async-errors: 3.1.1_express@4.17.1
express-session: 1.17.1
fast-json-stable-hash: 1.0.2
kamaitachi-common: github.com/zkldi/Kamaitachi-common/1cee2138f309c9c2e4c8382056099bbc32f3105a
kamaitachi-common: github.com/zkldi/Kamaitachi-common/9ec6904b471f44aebf5c486b80856020d3eef448
mongodb: 3.6.6
monk: 7.3.4
multer: 1.4.2
@@ -4637,8 +4637,8 @@ packages:
'@types/yoga-layout': 1.9.2
dev: true
github.com/zkldi/Kamaitachi-common/1cee2138f309c9c2e4c8382056099bbc32f3105a:
resolution: {tarball: https://codeload.github.com/zkldi/Kamaitachi-common/tar.gz/1cee2138f309c9c2e4c8382056099bbc32f3105a}
github.com/zkldi/Kamaitachi-common/9ec6904b471f44aebf5c486b80856020d3eef448:
resolution: {tarball: https://codeload.github.com/zkldi/Kamaitachi-common/tar.gz/9ec6904b471f44aebf5c486b80856020d3eef448}
name: kamaitachi-common
version: 0.1.0
dependencies:
@@ -1,3 +1,4 @@
import { version } from "commander";
import { Difficulties, Game, integer, Playtypes, IDStrings } from "kamaitachi-common";
import db from "../../db/db";
@@ -63,12 +64,19 @@ export function FindDDRChartOnSongHash(
});
}
/**
* Find a BMS chart on either its md5sum or its sha256sum.
* @param hash The md5 or sha256 hash to look for.
*/
export function FindBMSChartOnHash(hash: string) {
return db.charts.bms.findOne({
$or: [{ "data.hashMD5": hash }, { "data.hashSHA256": hash }],
});
}
/**
* Find a chart on its in-game-ID, playtype and difficulty.
*/
export function FindChartOnInGameID(
game: Game,
inGameID: number,
@@ -84,6 +92,30 @@ export function FindChartOnInGameID(
});
}
/**
* Find a chart on its in-game-ID, playtype, difficulty and version.
*/
export function FindChartOnInGameIDVersion(
game: Game,
inGameID: number,
playtype: Playtypes[Game],
difficulty: Difficulties[IDStrings],
version: string
) {
return db.charts[game].findOne({
"data.inGameID": inGameID,
versions: version,
playtype,
difficulty,
});
}
/**
* Find an SDVX Chart on its in game ID. This exists to handle
* oddities with SDVX difficulties - If "ANY_INF" is sent, it actually
* refers to any of INF, GRV, HVN or VVD. This is because some services treat
* all of those as the same difficulty, but we do not.
*/
export function FindSDVXChartOnInGameID(
inGameID: number,
playtype: Playtypes[Game],
@@ -9,9 +9,12 @@ import {
InvalidScoreFailure,
KTDataNotFoundFailure,
} from "../../../framework/score-importing/converter-failures";
import { FervidexScore } from "./types";
import { FervidexContext, FervidexScore } from "./types";
import { Lamps, Grades, Difficulties, Playtypes } from "kamaitachi-common";
import { FindChartOnInGameID } from "../../../../common/database-lookup/chart";
import {
FindChartOnInGameID,
FindChartOnInGameIDVersion,
} from "../../../../common/database-lookup/chart";
const LAMP_LOOKUP = {
0: "NO PLAY",
@@ -131,7 +134,7 @@ function SplitFervidexChartRef(ferDif: FervidexScore["chart"]) {
return { playtype, difficulty };
}
export const ConverterIRFervidex: ConverterFunction<FervidexScore, EmptyObject> = async (
export const ConverterIRFervidex: ConverterFunction<FervidexScore, FervidexContext> = async (
data,
context,
importType,
@@ -139,7 +142,13 @@ export const ConverterIRFervidex: ConverterFunction<FervidexScore, EmptyObject>
) => {
let { difficulty, playtype } = SplitFervidexChartRef(data.chart);
let chart = await FindChartOnInGameID("iidx", data.entry_id, playtype, difficulty);
let chart = await FindChartOnInGameIDVersion(
"iidx",
data.entry_id,
playtype,
difficulty,
context.version
);
if (!chart) {
throw new KTDataNotFoundFailure(
@@ -197,6 +206,9 @@ export const ConverterIRFervidex: ConverterFunction<FervidexScore, EmptyObject>
maxCombo: data.max_combo,
gaugeHistory,
gauge,
bp: data.bad + data.poor,
comboBreak: null,
gsm: data["2dx-gsm"],
},
},
scoreMeta: {
@@ -2,7 +2,7 @@ import { EmptyObject, KtLogger, ParserFunctionReturnsSync } from "../../../../ty
import p, { PrudenceSchema } from "prudence";
import ScoreImportFatalError from "../../../framework/score-importing/score-import-error";
import { FormatPrError, optNull } from "../../../../common/prudence";
import { FervidexScore } from "./types";
import { FervidexContext, FervidexScore } from "./types";
import { ConverterIRFervidex } from "./converter";
const PR_Fervidex: PrudenceSchema = {
@@ -40,13 +40,50 @@ const PR_Fervidex: PrudenceSchema = {
// we dont use it and we dont care.
pacemaker: p.optional(p.any),
"2dx-gsm": p.optional({
// @ts-expect-error recursive types error
EASY: [p.isBoundedInteger(0, 255)],
NORMAL: [p.isBoundedInteger(0, 255)],
HARD: [p.isBoundedInteger(0, 255)],
EX_HARD: [p.isBoundedInteger(0, 255)],
}),
};
/**
* Converts a string of the form LDJ:X:X:X:2020092900 into a game version.
* I don't really understand the software model format, so this is lazy.
*/
function ParseSoftwareModel(model: string) {
if (model.startsWith("LDJ")) {
// heroic verse
if (model.endsWith("2020092900")) {
return "27";
}
// i *really* don't care enough to support rootage or cannonballers.
throw new ScoreImportFatalError(400, `Unsupported Software Model ${model}.`);
} else if (model.startsWith("P2D")) {
// accept anything since this will probably change underfoot a lot.
return "inf2020";
}
throw new ScoreImportFatalError(400, `Unsupported Software Model ${model}.`);
}
interface FerHeaders {
model: string;
}
export function ParseFervidexSingle(
body: Record<string, unknown>,
headers: FerHeaders,
logger: KtLogger
): ParserFunctionReturnsSync<FervidexScore, EmptyObject> {
let err = p(body, PR_Fervidex);
): ParserFunctionReturnsSync<FervidexScore, FervidexContext> {
let version = ParseSoftwareModel(headers.model);
// more mods may be added in the future, so lets ignore excess keys.
let err = p(body, PR_Fervidex, undefined, { allowExcessKeys: true });
if (err) {
throw new ScoreImportFatalError(400, FormatPrError(err, "Invalid Fervidex Request?"));
@@ -54,7 +91,7 @@ export function ParseFervidexSingle(
// asserted using prudence.
return {
context: {},
context: { version },
game: "iidx",
iterable: ([body] as unknown) as FervidexScore[],
ConverterFunction: ConverterIRFervidex,
@@ -43,4 +43,15 @@ export interface FervidexScore {
score?: integer | null;
type?: string | null; // too lazy to type this and we dont use it.
};
"2dx-gsm"?: {
EASY: (number | null)[];
NORMAL: (number | null)[];
HARD: (number | null)[];
EX_HARD: (number | null)[];
} | null;
}
export interface FervidexContext {
version: string;
}
+2 -2
View File
@@ -20,7 +20,7 @@ import {
IIDXEamusementCSVData,
} from "./score-import/import-types/file/eamusement-iidx-csv/types";
import { BarbatosScore } from "./score-import/import-types/ir/barbatos/types";
import { FervidexScore } from "./score-import/import-types/ir/fervidex/types";
import { FervidexContext, FervidexScore } from "./score-import/import-types/ir/fervidex/types";
declare module "express-session" {
// Inject additional properties on express-session
@@ -137,7 +137,7 @@ export interface ImportTypeContextMap {
"file/batch-manual": BatchManualContext;
"ir/direct-manual": BatchManualContext;
"ir/barbatos": EmptyObject;
"ir/fervidex": EmptyObject;
"ir/fervidex": FervidexContext;
"ir/fervidex-static": EmptyObject;
}