mirror of
https://github.com/zkldi/Tachi.git
synced 2026-10-06 05:48:00 +03:00
Improve some unrelated tests while we're here.
This commit is contained in:
@@ -18,6 +18,7 @@ t.test("#CreateCalculatedData", async (t) => {
|
||||
const res = await CreateCalculatedData(TestingIIDXSPDryScore, Testing511SPA, 30, logger);
|
||||
|
||||
prAssert(
|
||||
t,
|
||||
res,
|
||||
{
|
||||
ktLampRating: p.equalTo(10),
|
||||
@@ -34,6 +35,7 @@ t.test("#CreateCalculatedData", async (t) => {
|
||||
);
|
||||
|
||||
prAssert(
|
||||
t,
|
||||
gitadoraRes,
|
||||
{
|
||||
skill: p.isPositiveNonZero,
|
||||
@@ -82,6 +84,7 @@ t.test("#CalculateDataForGamePT", (t) => {
|
||||
);
|
||||
|
||||
prAssert(
|
||||
t,
|
||||
res,
|
||||
{
|
||||
ktLampRating: "?number",
|
||||
@@ -105,6 +108,7 @@ t.test("#CalculateDataForGamePT", (t) => {
|
||||
);
|
||||
|
||||
prAssert(
|
||||
t,
|
||||
res,
|
||||
{
|
||||
ktLampRating: "?number",
|
||||
@@ -127,6 +131,7 @@ t.test("#CalculateDataForGamePT", (t) => {
|
||||
);
|
||||
|
||||
prAssert(
|
||||
t,
|
||||
res,
|
||||
{
|
||||
VF6: p.nullable(p.isPositive),
|
||||
@@ -148,6 +153,7 @@ t.test("#CalculateDataForGamePT", (t) => {
|
||||
);
|
||||
|
||||
prAssert(
|
||||
t,
|
||||
res,
|
||||
{
|
||||
MFCP: p.nullable(p.isPositiveInteger),
|
||||
@@ -170,6 +176,7 @@ t.test("#CalculateDataForGamePT", (t) => {
|
||||
);
|
||||
|
||||
prAssert(
|
||||
t,
|
||||
res,
|
||||
{
|
||||
MFCP: "null",
|
||||
@@ -192,6 +199,7 @@ t.test("#CalculateDataForGamePT", (t) => {
|
||||
);
|
||||
|
||||
prAssert(
|
||||
t,
|
||||
res,
|
||||
{
|
||||
rating: "?number",
|
||||
@@ -213,6 +221,7 @@ t.test("#CalculateDataForGamePT", (t) => {
|
||||
);
|
||||
|
||||
prAssert(
|
||||
t,
|
||||
res,
|
||||
{
|
||||
ktRating: "?number",
|
||||
@@ -234,6 +243,7 @@ t.test("#CalculateDataForGamePT", (t) => {
|
||||
);
|
||||
|
||||
prAssert(
|
||||
t,
|
||||
res,
|
||||
{
|
||||
ktRating: "?number",
|
||||
@@ -255,6 +265,7 @@ t.test("#CalculateDataForGamePT", (t) => {
|
||||
);
|
||||
|
||||
prAssert(
|
||||
t,
|
||||
res,
|
||||
{
|
||||
sieglinde: "?number",
|
||||
@@ -276,6 +287,7 @@ t.test("#CalculateDataForGamePT", (t) => {
|
||||
);
|
||||
|
||||
prAssert(
|
||||
t,
|
||||
res,
|
||||
{
|
||||
sieglinde: "?number",
|
||||
@@ -297,6 +309,7 @@ t.test("#CalculateDataForGamePT", (t) => {
|
||||
);
|
||||
|
||||
prAssert(
|
||||
t,
|
||||
res,
|
||||
{
|
||||
skill: "?number",
|
||||
@@ -318,6 +331,7 @@ t.test("#CalculateDataForGamePT", (t) => {
|
||||
);
|
||||
|
||||
prAssert(
|
||||
t,
|
||||
res,
|
||||
{
|
||||
skill: "?number",
|
||||
@@ -339,6 +353,7 @@ t.test("#CalculateDataForGamePT", (t) => {
|
||||
);
|
||||
|
||||
prAssert(
|
||||
t,
|
||||
res,
|
||||
{
|
||||
VF6: "?number",
|
||||
@@ -360,6 +375,7 @@ t.test("#CalculateDataForGamePT", (t) => {
|
||||
);
|
||||
|
||||
prAssert(
|
||||
t,
|
||||
res,
|
||||
{
|
||||
VF6: "?number",
|
||||
@@ -380,7 +396,7 @@ t.test("#CalculateDataForGamePT", (t) => {
|
||||
// logger
|
||||
// );
|
||||
|
||||
// prAssert(
|
||||
// prAssert(t ,
|
||||
// res,
|
||||
// {
|
||||
// jubility: "?number",
|
||||
@@ -402,7 +418,7 @@ t.test("#CalculateDataForGamePT", (t) => {
|
||||
// logger
|
||||
// );
|
||||
|
||||
// prAssert(res, {}, "Response should contain nulled keys for popn:9B");
|
||||
// prAssert(t ,res, {}, "Response should contain nulled keys for popn:9B");
|
||||
|
||||
// t.end();
|
||||
// });
|
||||
|
||||
@@ -29,23 +29,73 @@ t.test("#CalculateBPI", (t) => {
|
||||
}
|
||||
|
||||
t.equal(AA_BPI(KAVG_AA), 0, "A score of KAVG should be exactly 0BPI");
|
||||
isApproximately(AA_BPI(3393), 10.02, "A score with 3393 should be approximately 10.02BPI");
|
||||
isApproximately(AA_BPI(3481), 20.09, "A score with 3481 should be approximately 20.09BPI");
|
||||
isApproximately(AA_BPI(3535), 30.01, "A score with 3535 should be approximately 30.01BPI");
|
||||
isApproximately(AA_BPI(3572), 40.18, "A score with 3572 should be approximately 40.18BPI");
|
||||
isApproximately(AA_BPI(3597), 50.1, "A score with 3597 should be approximately 50.1BPI");
|
||||
isApproximately(AA_BPI(3615), 60.12, "A score with 3615 should be approximately 60.12BPI");
|
||||
isApproximately(AA_BPI(3628), 70.11, "A score with 3628 should be approximately 70.11BPI");
|
||||
isApproximately(AA_BPI(3638), 80.62, "A score with 3638 should be approximately 80.62BPI");
|
||||
isApproximately(AA_BPI(3645), 90.59, "A score with 3645 should be approximately 90.59BPI");
|
||||
isApproximately(
|
||||
t,
|
||||
AA_BPI(3393),
|
||||
10.02,
|
||||
"A score with 3393 should be approximately 10.02BPI"
|
||||
);
|
||||
isApproximately(
|
||||
t,
|
||||
AA_BPI(3481),
|
||||
20.09,
|
||||
"A score with 3481 should be approximately 20.09BPI"
|
||||
);
|
||||
isApproximately(
|
||||
t,
|
||||
AA_BPI(3535),
|
||||
30.01,
|
||||
"A score with 3535 should be approximately 30.01BPI"
|
||||
);
|
||||
isApproximately(
|
||||
t,
|
||||
AA_BPI(3572),
|
||||
40.18,
|
||||
"A score with 3572 should be approximately 40.18BPI"
|
||||
);
|
||||
isApproximately(t, AA_BPI(3597), 50.1, "A score with 3597 should be approximately 50.1BPI");
|
||||
isApproximately(
|
||||
t,
|
||||
AA_BPI(3615),
|
||||
60.12,
|
||||
"A score with 3615 should be approximately 60.12BPI"
|
||||
);
|
||||
isApproximately(
|
||||
t,
|
||||
AA_BPI(3628),
|
||||
70.11,
|
||||
"A score with 3628 should be approximately 70.11BPI"
|
||||
);
|
||||
isApproximately(
|
||||
t,
|
||||
AA_BPI(3638),
|
||||
80.62,
|
||||
"A score with 3638 should be approximately 80.62BPI"
|
||||
);
|
||||
isApproximately(
|
||||
t,
|
||||
AA_BPI(3645),
|
||||
90.59,
|
||||
"A score with 3645 should be approximately 90.59BPI"
|
||||
);
|
||||
t.equal(AA_BPI(WR_AA), 100, "A score of WR should be exactly 100BPI");
|
||||
|
||||
isApproximately(AA_BPI(3041), -5, "A score with 3628 should be approximately -5BPI");
|
||||
isApproximately(AA_BPI(2886), -9.99, "A score with 3638 should be approximately -9.99BPI");
|
||||
isApproximately(t, AA_BPI(3041), -5, "A score with 3628 should be approximately -5BPI");
|
||||
isApproximately(
|
||||
t,
|
||||
AA_BPI(2886),
|
||||
-9.99,
|
||||
"A score with 3638 should be approximately -9.99BPI"
|
||||
);
|
||||
|
||||
t.equal(AA_BPI(0), -15, "Excessively bad (vs kavg) scores should cap at -15BPI");
|
||||
|
||||
isApproximately(AA_BPI(MAX_AA), 244.56, "A score of MAX should be approximately 244.56BPI");
|
||||
isApproximately(
|
||||
t,
|
||||
AA_BPI(MAX_AA),
|
||||
244.56,
|
||||
"A score of MAX should be approximately 244.56BPI"
|
||||
);
|
||||
|
||||
t.end();
|
||||
});
|
||||
@@ -60,7 +110,7 @@ t.test("#CalculateBPI", (t) => {
|
||||
return CalculateBPI(KAVG_CL, WR_AFT, yourEx, MAX_CL, COEF_CL);
|
||||
}
|
||||
|
||||
isApproximately(CL_BPI(2307), 79.63);
|
||||
isApproximately(t, CL_BPI(2307), 79.63);
|
||||
|
||||
t.end();
|
||||
});
|
||||
@@ -79,19 +129,65 @@ t.test("#CalculateBPI", (t) => {
|
||||
}
|
||||
|
||||
t.equal(AFT_BPI(KAVG_AFT), 0, "A score of KAVG should be exactly 0BPI");
|
||||
isApproximately(AFT_BPI(2606), 10, "A score with 2606 should be approximately 10BPI");
|
||||
isApproximately(AFT_BPI(2675), 20.07, "A score with 2675 should be approximately 20.07BPI");
|
||||
isApproximately(AFT_BPI(2727), 30.18, "A score with 2727 should be approximately 30.18BPI");
|
||||
isApproximately(AFT_BPI(2767), 40.12, "A score with 2767 should be approximately 40.12BPI");
|
||||
isApproximately(AFT_BPI(2799), 50.06, "A score with 2799 should be approximately 50.06BPI");
|
||||
isApproximately(AFT_BPI(2826), 60.43, "A score with 2826 should be approximately 60.43BPI");
|
||||
isApproximately(AFT_BPI(2847), 70.3, "A score with 2847 should be approximately 70.3BPI");
|
||||
isApproximately(AFT_BPI(2865), 80.57, "A score with 2865 should be approximately 80.57BPI");
|
||||
isApproximately(AFT_BPI(2879), 90.18, "A score with 2879 should be approximately 90.18BPI");
|
||||
isApproximately(t, AFT_BPI(2606), 10, "A score with 2606 should be approximately 10BPI");
|
||||
isApproximately(
|
||||
t,
|
||||
AFT_BPI(2675),
|
||||
20.07,
|
||||
"A score with 2675 should be approximately 20.07BPI"
|
||||
);
|
||||
isApproximately(
|
||||
t,
|
||||
AFT_BPI(2727),
|
||||
30.18,
|
||||
"A score with 2727 should be approximately 30.18BPI"
|
||||
);
|
||||
isApproximately(
|
||||
t,
|
||||
AFT_BPI(2767),
|
||||
40.12,
|
||||
"A score with 2767 should be approximately 40.12BPI"
|
||||
);
|
||||
isApproximately(
|
||||
t,
|
||||
AFT_BPI(2799),
|
||||
50.06,
|
||||
"A score with 2799 should be approximately 50.06BPI"
|
||||
);
|
||||
isApproximately(
|
||||
t,
|
||||
AFT_BPI(2826),
|
||||
60.43,
|
||||
"A score with 2826 should be approximately 60.43BPI"
|
||||
);
|
||||
isApproximately(
|
||||
t,
|
||||
AFT_BPI(2847),
|
||||
70.3,
|
||||
"A score with 2847 should be approximately 70.3BPI"
|
||||
);
|
||||
isApproximately(
|
||||
t,
|
||||
AFT_BPI(2865),
|
||||
80.57,
|
||||
"A score with 2865 should be approximately 80.57BPI"
|
||||
);
|
||||
isApproximately(
|
||||
t,
|
||||
AFT_BPI(2879),
|
||||
90.18,
|
||||
"A score with 2879 should be approximately 90.18BPI"
|
||||
);
|
||||
t.equal(AFT_BPI(WR_AFT), 100, "A score of WR should be exactly 100BPI");
|
||||
|
||||
isApproximately(AFT_BPI(2423), -4.99, "A score with 2423 should be approximately -4.99BPI");
|
||||
isApproximately(
|
||||
t,
|
||||
AFT_BPI(2423),
|
||||
-4.99,
|
||||
"A score with 2423 should be approximately -4.99BPI"
|
||||
);
|
||||
isApproximately(
|
||||
t,
|
||||
AFT_BPI(2354),
|
||||
-10.04,
|
||||
"A score with 2354 should be approximately -10.04BPI"
|
||||
@@ -100,6 +196,7 @@ t.test("#CalculateBPI", (t) => {
|
||||
t.equal(AFT_BPI(0), -15, "Excessively bad (vs kavg) scores should cap at -15BPI");
|
||||
|
||||
isApproximately(
|
||||
t,
|
||||
AFT_BPI(MAX_AFT),
|
||||
431.57,
|
||||
"A score of MAX should be approximately 431.57BPI"
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { ChartDocument, Game } from "tachi-common";
|
||||
import t from "tap";
|
||||
import { GetGradeFromPercent } from "./score-utils";
|
||||
import { isApproximately } from "test-utils/asserts";
|
||||
import { Testing511SPA } from "test-utils/test-data";
|
||||
import { GenericCalculatePercent, GetGradeFromPercent, ValidatePercent } from "./score-utils";
|
||||
|
||||
t.test("#GetGradeForPercent", (t) => {
|
||||
t.equal(
|
||||
@@ -31,3 +34,68 @@ t.test("#GetGradeForPercent", (t) => {
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("#GenericCalculatePercent", (t) => {
|
||||
const f = (game: Game, score: number, equal: number) =>
|
||||
isApproximately(t, GenericCalculatePercent(game, score), equal);
|
||||
|
||||
for (const game of ["iidx", "bms", "pms"] as const) {
|
||||
isApproximately(t, GenericCalculatePercent(game, 1240, Testing511SPA), 78.88);
|
||||
isApproximately(t, GenericCalculatePercent(game, 0, Testing511SPA), 0);
|
||||
}
|
||||
|
||||
f("popn", 100_000, 100);
|
||||
f("popn", 50_000, 50);
|
||||
f("popn", 0, 0);
|
||||
|
||||
f("maimai", 10, 10);
|
||||
f("maimai", 101.12, 101.12);
|
||||
|
||||
for (const game of ["usc", "sdvx"] as const) {
|
||||
f(game, 10_000_000, 100);
|
||||
f(game, 5_000_000, 50);
|
||||
f(game, 9_950_000, 99.5);
|
||||
f(game, 1_370_000, 13.7);
|
||||
f(game, 0, 0);
|
||||
}
|
||||
|
||||
for (const game of ["ddr", "museca", "chunithm", "wacca"] as const) {
|
||||
f(game, 1_000_000, 100);
|
||||
f(game, 500_000, 50);
|
||||
f(game, 993_121, 99.3121);
|
||||
f(game, 1_000, 0.1);
|
||||
}
|
||||
|
||||
t.throws(() => GenericCalculatePercent("unknown_game" as Game, 100), {
|
||||
message: /Invalid game/u,
|
||||
});
|
||||
t.throws(() => GenericCalculatePercent("iidx", 100), {
|
||||
message: /No Chart passed/u,
|
||||
});
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("#ValidatePercent", (t) => {
|
||||
for (const playtype of ["SP", "DP"] as const) {
|
||||
t.doesNotThrow(() => ValidatePercent("iidx", playtype, 90, Testing511SPA));
|
||||
t.doesNotThrow(() => ValidatePercent("iidx", playtype, 0, Testing511SPA));
|
||||
t.doesNotThrow(() => ValidatePercent("iidx", playtype, 100, Testing511SPA));
|
||||
|
||||
t.throws(() => ValidatePercent("iidx", playtype, -50, Testing511SPA));
|
||||
t.throws(() => ValidatePercent("iidx", playtype, 101, Testing511SPA));
|
||||
}
|
||||
|
||||
const m = (maxPercent: number) => ({ data: { maxPercent } } as ChartDocument);
|
||||
|
||||
t.doesNotThrow(() => ValidatePercent("maimai", "Single", 90, m(100)));
|
||||
t.doesNotThrow(() => ValidatePercent("maimai", "Single", 100, m(100)));
|
||||
t.doesNotThrow(() => ValidatePercent("maimai", "Single", 0, m(100)));
|
||||
t.doesNotThrow(() => ValidatePercent("maimai", "Single", 110, m(120)));
|
||||
t.doesNotThrow(() => ValidatePercent("maimai", "Single", 120, m(120)));
|
||||
t.throws(() => ValidatePercent("maimai", "Single", 130, m(120)), {
|
||||
message: /expected a number less than 120/u,
|
||||
});
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
@@ -58,23 +58,33 @@ export function GenericCalculatePercent(game: Game, score: number, chart?: Chart
|
||||
return (score / 10_000_000) * 100;
|
||||
case "popn":
|
||||
return (score / 100_000) * 100;
|
||||
case "gitadora":
|
||||
case "maimai":
|
||||
// score in maimai is actually just your percent, since nobody cares about
|
||||
// money score.
|
||||
return score;
|
||||
case "bms":
|
||||
case "pms":
|
||||
case "iidx":
|
||||
if (!chart) {
|
||||
logger.severe("No Chart passed to GenericCalcPercent but game was iidx/bms.");
|
||||
logger.severe("No Chart passed to GenericCalcPercent but game was iidx/bms/pms.");
|
||||
throw new InternalFailure(
|
||||
"No Chart passed to GenericCalcPercent but game was iidx/bms."
|
||||
"No Chart passed to GenericCalcPercent but game was iidx/bms/pms."
|
||||
);
|
||||
}
|
||||
|
||||
// Yeah, we declare it like this so the below return is actually clear.
|
||||
// eslint-disable-next-line no-case-declarations
|
||||
const MAX =
|
||||
(chart as ChartDocument<"iidx:SP" | "bms:7K" | "bms:14K" | "iidx:DP">).data
|
||||
.notecount * 2;
|
||||
(
|
||||
chart as ChartDocument<
|
||||
| "iidx:SP"
|
||||
| "bms:7K"
|
||||
| "bms:14K"
|
||||
| "pms:Controller"
|
||||
| "pms:Keyboard"
|
||||
| "iidx:DP"
|
||||
>
|
||||
).data.notecount * 2;
|
||||
|
||||
return (100 * score) / MAX;
|
||||
default:
|
||||
@@ -100,16 +110,22 @@ export function ValidatePercent(
|
||||
const mmChart = chart as ChartDocument<"maimai:Single">;
|
||||
if (percent > mmChart.data.maxPercent) {
|
||||
throw new InvalidScoreFailure(
|
||||
`Invalid percent - expected less than ${mmChart.data.maxPercent}.`
|
||||
`Invalid percent - expected a number less than ${mmChart.data.maxPercent}.`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
const gptConfig = GetGamePTConfig(game, playtype);
|
||||
|
||||
if (percent > gptConfig.percentMax) {
|
||||
throw new InvalidScoreFailure(
|
||||
`Invalid percent of ${percent} - expected a value less than ${gptConfig.percentMax}% (${chart.songID} ${chart.playtype} ${chart.difficulty}).`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const gptConfig = GetGamePTConfig(game, playtype);
|
||||
|
||||
if (percent > gptConfig.percentMax) {
|
||||
if (percent < 0) {
|
||||
throw new InvalidScoreFailure(
|
||||
`Invalid percent of ${percent} - expected a value less than ${gptConfig.percentMax}% (${chart.songID} ${chart.playtype} ${chart.difficulty}).`
|
||||
`Invalid percent of ${percent} - Expected a positive number? (${chart.songID} ${chart.playtype} ${chart.difficulty})`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,26 @@
|
||||
import { rootLogger } from "lib/logger/logger";
|
||||
import Prudence, { PrudenceSchema } from "prudence";
|
||||
import t from "tap";
|
||||
|
||||
export function isApproximately(number: number, target: number, message?: string, lenience = 0.01) {
|
||||
const result = t.ok(Math.abs(number - target) < lenience, message);
|
||||
export function isApproximately(
|
||||
t: Tap.Test,
|
||||
number: number,
|
||||
target: number,
|
||||
message?: string,
|
||||
lenience = 0.01
|
||||
) {
|
||||
const result = Math.abs(number - target) < lenience;
|
||||
|
||||
if (!result) {
|
||||
rootLogger.error(`${number} was not close enough to ${target}`);
|
||||
return t.fail(`${number} was not close enough to ${target}`, {
|
||||
errmsg: `${number} was not close enough to ${target}`,
|
||||
});
|
||||
}
|
||||
|
||||
t.pass(message);
|
||||
|
||||
// return true;
|
||||
}
|
||||
|
||||
export function prAssert(
|
||||
t: Tap.Test,
|
||||
obj: Record<string, unknown> | unknown,
|
||||
schema: PrudenceSchema,
|
||||
message = "Unnamed Prudence Assertion"
|
||||
|
||||
Reference in New Issue
Block a user