mirror of
https://github.com/zkldi/Tachi.git
synced 2026-09-30 19:07:58 +03:00
ir/usc tests
This commit is contained in:
+23
-12
@@ -22,15 +22,18 @@
|
||||
"plugin:import/errors"
|
||||
],
|
||||
"rules": {
|
||||
"prettier/prettier": ["error", {
|
||||
"printWidth": 100,
|
||||
"tabWidth": 4,
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"trailingComma": "es5",
|
||||
"bracketSpacing": true,
|
||||
"endOfLine": "auto"
|
||||
}],
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{
|
||||
"printWidth": 100,
|
||||
"tabWidth": 4,
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"trailingComma": "es5",
|
||||
"bracketSpacing": true,
|
||||
"endOfLine": "auto"
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"require-await": "warn",
|
||||
@@ -42,7 +45,10 @@
|
||||
"no-eval": "error",
|
||||
"no-var": "error",
|
||||
"no-new-object": "error",
|
||||
"quote-props": ["error", "as-needed"],
|
||||
"quote-props": [
|
||||
"error",
|
||||
"as-needed"
|
||||
],
|
||||
"no-array-constructor": "error",
|
||||
"prefer-template": "error",
|
||||
"prefer-promise-reject-errors": "error",
|
||||
@@ -73,9 +79,14 @@
|
||||
"no-throw-literal": "error",
|
||||
"no-unmodified-loop-condition": "error",
|
||||
"no-unused-expressions": "error",
|
||||
// "no-unused-vars": [
|
||||
// "warn",
|
||||
// {
|
||||
// "match": "logger"
|
||||
// }
|
||||
// ],
|
||||
"no-useless-call": "error",
|
||||
"no-useless-return": "error",
|
||||
"require-unicode-regexp": "error",
|
||||
|
||||
"require-unicode-regexp": "error"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
import t from "tap";
|
||||
import db, { CloseMongoConnection } from "../../../../../external/mongo/db";
|
||||
import { ConverterIRUSC, DeriveLamp, DeriveNoteMod } from "./converter";
|
||||
import d from "deepmerge";
|
||||
import { uscChart, uscScore } from "../../../../../test-utils/test-data";
|
||||
import CreateLogCtx from "../../../../logger/logger";
|
||||
import ResetDBState from "../../../../../test-utils/reset-db-state";
|
||||
import { USCClientScore } from "../../../../../server/router/ir/usc/usc";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
t.test("#DeriveLamp", (t) => {
|
||||
t.equal(DeriveLamp(uscScore, logger), "EXCESSIVE CLEAR");
|
||||
|
||||
t.equal(DeriveLamp(d(uscScore, { options: { gaugeType: 0 }, gauge: 50 }), logger), "FAILED");
|
||||
|
||||
t.equal(DeriveLamp(d(uscScore, { options: { gaugeType: 0 }, gauge: 70 }), logger), "CLEAR");
|
||||
|
||||
t.equal(
|
||||
DeriveLamp(d(uscScore, { options: { gaugeType: 1 }, gauge: 0.1 }), logger),
|
||||
"EXCESSIVE CLEAR"
|
||||
);
|
||||
|
||||
t.equal(DeriveLamp(d(uscScore, { options: { gaugeType: 1 }, gauge: 0 }), logger), "FAILED");
|
||||
|
||||
t.equal(
|
||||
DeriveLamp(
|
||||
d(uscScore, { score: 10_000_000, options: { gaugeType: 1 }, gauge: 0.1 }),
|
||||
logger
|
||||
),
|
||||
"PERFECT ULTIMATE CHAIN"
|
||||
);
|
||||
|
||||
// error: 0 should not take priority over score 10million
|
||||
t.equal(
|
||||
DeriveLamp(
|
||||
d(uscScore, {
|
||||
score: 10_000_000,
|
||||
options: { gaugeType: 1 },
|
||||
gauge: 0.1,
|
||||
error: 0,
|
||||
}),
|
||||
logger
|
||||
),
|
||||
"PERFECT ULTIMATE CHAIN"
|
||||
);
|
||||
|
||||
t.equal(
|
||||
DeriveLamp(
|
||||
d(uscScore, {
|
||||
score: 9_000_000,
|
||||
options: { gaugeType: 0 },
|
||||
gauge: 15,
|
||||
error: 0,
|
||||
}),
|
||||
logger
|
||||
),
|
||||
"ULTIMATE CHAIN"
|
||||
);
|
||||
|
||||
t.throws(() => DeriveLamp(d(uscScore, { options: { gaugeType: 2 } }), logger));
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("#DeriveNoteMod", (t) => {
|
||||
t.equal(DeriveNoteMod(uscScore), "MIRROR");
|
||||
|
||||
t.equal(DeriveNoteMod(d(uscScore, { options: { random: true } })), "MIR-RAN");
|
||||
|
||||
t.equal(DeriveNoteMod(d(uscScore, { options: { random: false, mirror: false } })), "NORMAL");
|
||||
t.equal(DeriveNoteMod(d(uscScore, { options: { random: true, mirror: false } })), "RANDOM");
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
const dm = (p: Partial<USCClientScore> | any) =>
|
||||
ConverterIRUSC(d(uscScore, p), { chart: uscChart }, "ir/usc", logger);
|
||||
|
||||
t.test("#ConverterIRUSC", (t) => {
|
||||
t.beforeEach(ResetDBState);
|
||||
|
||||
t.test("Should convert a score", async (t) => {
|
||||
const res = await dm({});
|
||||
|
||||
t.hasStrict(res, {
|
||||
song: {
|
||||
id: 1,
|
||||
},
|
||||
chart: {
|
||||
chartID: uscChart.chartID,
|
||||
},
|
||||
dryScore: {},
|
||||
} as any);
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should reject scores with invalid hit windows", (t) => {
|
||||
t.rejects(dm({ windows: { perfect: 0 } }));
|
||||
t.rejects(dm({ windows: { good: 0 } }));
|
||||
t.rejects(dm({ windows: { hold: 0 } }));
|
||||
t.rejects(dm({ windows: { miss: 0 } }));
|
||||
t.rejects(dm({ windows: { slam: 0 } }));
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should reject scores with invalid autoflags", (t) => {
|
||||
t.rejects(dm({ options: { autoFlags: 1 } }));
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should throw an InternalFailure on song-chart desync", async (t) => {
|
||||
await db.songs.usc.remove({});
|
||||
t.rejects(dm({}));
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.teardown(CloseMongoConnection);
|
||||
@@ -5,7 +5,7 @@ import { InternalFailure, InvalidScoreFailure } from "../../../framework/common/
|
||||
import { GenericGetGradeAndPercent } from "../../../framework/common/score-utils";
|
||||
import { IRUSCContext } from "./types";
|
||||
import { Lamps } from "kamaitachi-common";
|
||||
import uuid from "uuid";
|
||||
import { v4 as UUIDv4 } from "uuid";
|
||||
import { ConverterFunction } from "../../common/types";
|
||||
import { DryScore } from "../../../framework/common/types";
|
||||
import {
|
||||
@@ -16,7 +16,10 @@ import {
|
||||
USC_DEFAULT_SLAM,
|
||||
} from "../../../../constants/usc-ir";
|
||||
|
||||
function DeriveNoteMod(data: USCClientScore): "NORMAL" | "MIRROR" | "RANDOM" | "MIR-RAN" {
|
||||
/**
|
||||
* Interprets the "note mod" used based on the USC score.
|
||||
*/
|
||||
export function DeriveNoteMod(data: USCClientScore): "NORMAL" | "MIRROR" | "RANDOM" | "MIR-RAN" {
|
||||
if (data.options.mirror && data.options.random) {
|
||||
return "MIR-RAN";
|
||||
} else if (data.options.mirror) {
|
||||
@@ -28,7 +31,10 @@ function DeriveNoteMod(data: USCClientScore): "NORMAL" | "MIRROR" | "RANDOM" | "
|
||||
return "NORMAL";
|
||||
}
|
||||
|
||||
function DeriveLamp(scoreDoc: USCClientScore, logger: KtLogger): Lamps["usc:Single"] {
|
||||
/**
|
||||
* Determines the lamp of a USC score.
|
||||
*/
|
||||
export function DeriveLamp(scoreDoc: USCClientScore, logger: KtLogger): Lamps["usc:Single"] {
|
||||
if (scoreDoc.score === 10_000_000) {
|
||||
return "PERFECT ULTIMATE CHAIN";
|
||||
} else if (scoreDoc.error === 0) {
|
||||
@@ -98,7 +104,7 @@ export const ConverterIRUSC: ConverterFunction<USCClientScore, IRUSCContext> = a
|
||||
scoreMeta: {
|
||||
gaugeMod: data.options.gaugeOpt === 0 ? "NORMAL" : "HARD",
|
||||
noteMod: DeriveNoteMod(data),
|
||||
replayID: uuid.v4(),
|
||||
replayID: UUIDv4(),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import t from "tap";
|
||||
import { CloseMongoConnection } from "../../../../../external/mongo/db";
|
||||
import { uscChart, uscScore } from "../../../../../test-utils/test-data";
|
||||
import CreateLogCtx from "../../../../logger/logger";
|
||||
import { ParseIRUSC } from "./parser";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
t.test("#ParseIRUSC", (t) => {
|
||||
t.test("Should validate and convert a score into an iterable", (t) => {
|
||||
const res = ParseIRUSC(
|
||||
({ score: uscScore } as unknown) as Record<string, unknown>,
|
||||
uscChart,
|
||||
logger
|
||||
);
|
||||
|
||||
t.hasStrict(res, {
|
||||
game: "usc",
|
||||
context: {
|
||||
chart: uscChart,
|
||||
},
|
||||
iterable: [uscScore],
|
||||
} as any);
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.teardown(CloseMongoConnection);
|
||||
@@ -0,0 +1,13 @@
|
||||
[
|
||||
{
|
||||
"title": "ALBIDA Powerless Mix",
|
||||
"artist": "無力P",
|
||||
"id": 1,
|
||||
"firstVersion": null,
|
||||
"alt-titles": [],
|
||||
"search-titles": [],
|
||||
"data": {
|
||||
"sdvxEquiv": null
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -11,8 +11,16 @@ import {
|
||||
} from "kamaitachi-common";
|
||||
import path from "path";
|
||||
import db from "../external/mongo/db";
|
||||
import {
|
||||
USC_DEFAULT_HOLD,
|
||||
USC_DEFAULT_MISS,
|
||||
USC_DEFAULT_NEAR,
|
||||
USC_DEFAULT_PERFECT,
|
||||
USC_DEFAULT_SLAM,
|
||||
} from "../lib/constants/usc-ir";
|
||||
import { DryScore } from "../lib/score-import/framework/common/types";
|
||||
import { BarbatosScore } from "../lib/score-import/import-types/ir/barbatos/types";
|
||||
import { USCClientScore } from "../server/router/ir/usc/usc";
|
||||
|
||||
const file = (name: string) => path.join(__dirname, "/test-data", name);
|
||||
|
||||
@@ -184,3 +192,44 @@ export const barbScore: BarbatosScore = {
|
||||
score: 9_000_000,
|
||||
song_id: 1,
|
||||
};
|
||||
|
||||
export const uscChart: ChartDocument<"usc:Single"> = {
|
||||
rgcID: null,
|
||||
chartID: "USC_CHART_ID",
|
||||
difficulty: "NOV",
|
||||
songID: 1,
|
||||
playtype: "Single",
|
||||
levelNum: 1,
|
||||
level: "1",
|
||||
flags: {
|
||||
CUSTOM: true,
|
||||
},
|
||||
data: {
|
||||
hashSHA256: "USC_CHART_HASH",
|
||||
},
|
||||
isPrimary: true,
|
||||
versions: [],
|
||||
};
|
||||
|
||||
export const uscScore: USCClientScore = {
|
||||
crit: 100,
|
||||
error: 5,
|
||||
near: 50,
|
||||
gauge: 80,
|
||||
options: {
|
||||
autoFlags: 0,
|
||||
gaugeOpt: 0,
|
||||
gaugeType: 1,
|
||||
mirror: true,
|
||||
random: false,
|
||||
},
|
||||
score: 9_000_000,
|
||||
timestamp: 0,
|
||||
windows: {
|
||||
good: USC_DEFAULT_NEAR,
|
||||
perfect: USC_DEFAULT_PERFECT,
|
||||
hold: USC_DEFAULT_HOLD,
|
||||
miss: USC_DEFAULT_MISS,
|
||||
slam: USC_DEFAULT_SLAM,
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user