mirror of
https://github.com/zkldi/Tachi.git
synced 2026-10-12 09:18:25 +03:00
feat: remove MER from codebase
Hasn't been used in forever.
This commit is contained in:
@@ -533,16 +533,6 @@ function ImportTypeInfoCard({
|
||||
key="Batch Manual"
|
||||
/>
|
||||
);
|
||||
case "file/mer-iidx":
|
||||
return (
|
||||
<ImportInfoCard
|
||||
name="MER .json"
|
||||
href="iidx-mer"
|
||||
desc="Use a MER-exported .json file to synchronise scores."
|
||||
moreInfo="Note: Scores that do not match an existing song on the site will be orphaned, and anyone can see your orphaned scores. Don't be an idiot. I highly recommend using Fervidex instead."
|
||||
key="MER .json"
|
||||
/>
|
||||
);
|
||||
case "file/pli-iidx-csv":
|
||||
return (
|
||||
<ImportInfoCard
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
import ImportFileInfo from "components/imports/ImportFileInfo";
|
||||
import useSetSubheader from "components/layout/header/useSetSubheader";
|
||||
import React from "react";
|
||||
|
||||
export default function MerJSONPage() {
|
||||
useSetSubheader(["Import Scores", "MER .json"]);
|
||||
|
||||
return (
|
||||
<ImportFileInfo
|
||||
acceptMime="application/json"
|
||||
importType="file/mer-iidx"
|
||||
name="MER .json"
|
||||
parseFunction={ParseFunction}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function ParseFunction(d: string) {
|
||||
const json = JSON.parse(d);
|
||||
|
||||
if (!Array.isArray(json)) {
|
||||
throw new Error(`Expected a JSON array. Is this valid MER?`);
|
||||
}
|
||||
|
||||
return {
|
||||
valid: true,
|
||||
info: {
|
||||
Scores: json.length,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -11,7 +11,6 @@ const FILE_IMPORT_TYPES: Record<FileUploadImportTypes, true> = {
|
||||
"file/eamusement-sdvx-csv": true,
|
||||
"file/batch-manual": true,
|
||||
"file/solid-state-squad": true,
|
||||
"file/mer-iidx": true,
|
||||
"file/pli-iidx-csv": true,
|
||||
"file/mypagescraper-records-csv": true,
|
||||
"file/mypagescraper-player-csv": true,
|
||||
|
||||
@@ -2,7 +2,6 @@ export type FileUploadImportTypes =
|
||||
| "file/batch-manual"
|
||||
| "file/eamusement-iidx-csv"
|
||||
| "file/eamusement-sdvx-csv"
|
||||
| "file/mer-iidx"
|
||||
| "file/mypagescraper-player-csv"
|
||||
| "file/mypagescraper-records-csv"
|
||||
| "file/pli-iidx-csv"
|
||||
|
||||
@@ -51,7 +51,6 @@ is set to indicate that this was done with User Intent.
|
||||
| `file/eamusement-iidx-csv` | The E-amusement CSV format for IIDX. This type accepts both Pre-HV and Post-HV formats. | Kamaitachi | Yes |
|
||||
| `file/batch-manual` | The Tachi BATCH-MANUAL format submitted through a multipart form. | Kamaitachi & Bokutachi | Yes |
|
||||
| `file/solid-state-squad` | The IIDX XML output by Solid State Squad. | Kamaitachi | Yes |
|
||||
| `file/mer-iidx` | The IIDX JSON output from MER. | Kamaitachi | Yes |
|
||||
| `file/pli-iidx-csv` | Same as eamusement's IIDX CSV, but output from PLI. | Kamaitachi | Yes |
|
||||
| `ir/direct-manual` | The Tachi BATCH-MANUAL format but submitted in a HTTP Request body as `application/json`. | Kamaitachi & Bokutachi | Depends on Header |
|
||||
| `ir/barbatos` | Barbatos's format submitted in a HTTP Request Body. | Kamaitachi | No |
|
||||
|
||||
@@ -68,7 +68,6 @@ the main benefits for us are as follows:
|
||||
"file/eamusement-iidx-csv",
|
||||
"file/batch-manual",
|
||||
"file/solid-state-squad",
|
||||
"file/mer-iidx",
|
||||
"file/pli-iidx-csv",
|
||||
"ir/direct-manual",
|
||||
"ir/barbatos",
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
"file/eamusement-iidx-csv",
|
||||
"file/batch-manual",
|
||||
"file/solid-state-squad",
|
||||
"file/mer-iidx",
|
||||
"file/pli-iidx-csv",
|
||||
"file/mypagescraper-records-csv",
|
||||
"file/mypagescraper-player-csv",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { ConverterFailure } from "../../framework/common/converter-failures";
|
||||
import type { DryScore } from "../../framework/common/types";
|
||||
import type { SDVXEamusementCSVData } from "../file/eamusement-sdvx-csv/types";
|
||||
import type { MerScore } from "../file/mer-iidx/types";
|
||||
import type { S3Score } from "../file/solid-state-squad/types";
|
||||
import type { MyPageRecordsParsedPB } from "../file/wacca-mypage-scraper/types";
|
||||
import type { BarbatosContext, BarbatosScore, BarbatosSDVX6Score } from "../ir/barbatos/types";
|
||||
@@ -34,7 +33,6 @@ export interface ImportTypeDataMap {
|
||||
"file/eamusement-sdvx-csv": SDVXEamusementCSVData;
|
||||
"file/batch-manual": BatchManualScore;
|
||||
"file/solid-state-squad": S3Score;
|
||||
"file/mer-iidx": MerScore;
|
||||
"file/pli-iidx-csv": IIDXEamusementCSVData;
|
||||
"file/mypagescraper-records-csv": MyPageRecordsParsedPB;
|
||||
"file/mypagescraper-player-csv": never;
|
||||
@@ -79,7 +77,6 @@ export interface ImportTypeContextMap {
|
||||
"file/eamusement-sdvx-csv": EmptyObject;
|
||||
"file/batch-manual": BatchManualContext;
|
||||
"file/solid-state-squad": EmptyObject;
|
||||
"file/mer-iidx": EmptyObject;
|
||||
"file/pli-iidx-csv": IIDXEamusementCSVContext;
|
||||
"file/mypagescraper-records-csv": EmptyObject;
|
||||
"file/mypagescraper-player-csv": EmptyObject;
|
||||
|
||||
@@ -6,7 +6,6 @@ import { ConvertAPIKaiSDVX } from "./common/api-kai/sdvx/converter";
|
||||
import { ConverterBatchManual } from "./common/batch-manual/converter";
|
||||
import ConvertEamIIDXCSV from "./common/eamusement-iidx-csv/converter";
|
||||
import ConvertEamSDVXCSV from "./file/eamusement-sdvx-csv/converter";
|
||||
import { ConvertFileMerIIDX } from "./file/mer-iidx/converter";
|
||||
import { ConvertFileS3 } from "./file/solid-state-squad/converter";
|
||||
import ConvertMyPageScraperRecordsCSV from "./file/wacca-mypage-scraper/converter";
|
||||
import { ConverterIRBarbatos } from "./ir/barbatos/converter";
|
||||
@@ -28,7 +27,6 @@ export type ConverterMap = {
|
||||
export const Converters: ConverterMap = {
|
||||
"file/solid-state-squad": ConvertFileS3,
|
||||
"file/batch-manual": ConverterBatchManual,
|
||||
"file/mer-iidx": ConvertFileMerIIDX,
|
||||
"file/pli-iidx-csv": ConvertEamIIDXCSV,
|
||||
"file/eamusement-iidx-csv": ConvertEamIIDXCSV,
|
||||
"file/eamusement-sdvx-csv": ConvertEamSDVXCSV,
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
import { ConvertFileMerIIDX } from "./converter";
|
||||
import deepmerge from "deepmerge";
|
||||
import db from "external/mongo/db";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import t from "tap";
|
||||
import ResetDBState from "test-utils/resets";
|
||||
import { LoadTachiIIDXData, Testing511Song, Testing511SPA } from "test-utils/test-data";
|
||||
import type { MerScore } from "./types";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
t.test("#ConvertFileMerIIDX", (t) => {
|
||||
t.beforeEach(ResetDBState);
|
||||
|
||||
const MerScore = {
|
||||
music_id: 1000,
|
||||
play_type: "SINGLE",
|
||||
diff_type: "ANOTHER",
|
||||
score: 1000,
|
||||
miss_count: 21,
|
||||
clear_type: "CLEAR",
|
||||
update_time: "2021-03-24 07:15:22",
|
||||
} as const;
|
||||
|
||||
function merc(g: Partial<MerScore> = {}) {
|
||||
return ConvertFileMerIIDX(deepmerge(MerScore, g), {}, "file/mer-iidx", logger);
|
||||
}
|
||||
|
||||
t.test("Valid Conversion", async (t) => {
|
||||
const res = await ConvertFileMerIIDX(MerScore, {}, "file/mer-iidx", logger);
|
||||
|
||||
t.hasStrict(
|
||||
res,
|
||||
{
|
||||
song: Testing511Song,
|
||||
chart: Testing511SPA,
|
||||
dryScore: {
|
||||
game: "iidx",
|
||||
comment: null,
|
||||
importType: "file/mer-iidx",
|
||||
service: "MER",
|
||||
scoreData: {
|
||||
score: 1000,
|
||||
lamp: "CLEAR",
|
||||
judgements: {},
|
||||
optional: {
|
||||
bp: 21,
|
||||
},
|
||||
},
|
||||
scoreMeta: {},
|
||||
timeAchieved: 1616537722000,
|
||||
},
|
||||
},
|
||||
"Should return the converted dry score."
|
||||
);
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Valid DP Conversion", async (t) => {
|
||||
await LoadTachiIIDXData();
|
||||
const res = await merc({ play_type: "DOUBLE" });
|
||||
|
||||
t.hasStrict(
|
||||
res,
|
||||
{
|
||||
song: { id: 1 },
|
||||
chart: { playtype: "DP", data: { inGameID: 1000 } },
|
||||
dryScore: {
|
||||
game: "iidx",
|
||||
comment: null,
|
||||
importType: "file/mer-iidx",
|
||||
service: "MER",
|
||||
scoreData: {
|
||||
score: 1000,
|
||||
lamp: "CLEAR",
|
||||
judgements: {},
|
||||
optional: {
|
||||
bp: 21,
|
||||
},
|
||||
},
|
||||
scoreMeta: {},
|
||||
timeAchieved: 1616537722000,
|
||||
},
|
||||
},
|
||||
"Should return the converted dry score."
|
||||
);
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Invalid Chart", (t) => {
|
||||
t.rejects(() => merc({ diff_type: "LEGGENDARIA" }), {
|
||||
message: /Could not find chart with musicID 1000 \(SP LEGGENDARIA/u,
|
||||
});
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Invalid Song", (t) => {
|
||||
t.rejects(() => merc({ music_id: 0 }), {
|
||||
message: /Could not find chart with musicID 0/u,
|
||||
});
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should log severe on Song-Chart Desync", async (t) => {
|
||||
await db.songs.iidx.remove({});
|
||||
|
||||
t.rejects(() => merc(), {
|
||||
message: /Song-Chart Desync on songID 1/u,
|
||||
});
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Invalid Date", (t) => {
|
||||
t.rejects(() => merc({ update_time: "INVALID" }), {
|
||||
message: /Invalid\/Unparsable score timestamp of INVALID/u,
|
||||
});
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.end();
|
||||
});
|
||||
@@ -1,91 +0,0 @@
|
||||
import {
|
||||
InternalFailure,
|
||||
SkipScoreFailure,
|
||||
SongOrChartNotFoundFailure,
|
||||
} from "../../../framework/common/converter-failures";
|
||||
import { ParseDateFromString } from "../../../framework/common/score-utils";
|
||||
import { FindIIDXChartOnInGameID } from "utils/queries/charts";
|
||||
import { FindSongOnID } from "utils/queries/songs";
|
||||
import type { DryScore } from "../../../framework/common/types";
|
||||
import type { ConverterFunction } from "../../common/types";
|
||||
import type { MerScore } from "./types";
|
||||
import type { GetEnumValue } from "tachi-common/types/metrics";
|
||||
import type { EmptyObject } from "utils/types";
|
||||
|
||||
function ConvertMERLamp(lamp: MerScore["clear_type"]): GetEnumValue<"iidx:DP" | "iidx:SP", "lamp"> {
|
||||
if (lamp === "FULLCOMBO CLEAR") {
|
||||
return "FULL COMBO";
|
||||
}
|
||||
|
||||
return lamp;
|
||||
}
|
||||
|
||||
export const ConvertFileMerIIDX: ConverterFunction<MerScore, EmptyObject> = async (
|
||||
data,
|
||||
context,
|
||||
importType,
|
||||
logger
|
||||
) => {
|
||||
const playtype = data.play_type === "SINGLE" ? "SP" : "DP";
|
||||
|
||||
if (data.diff_type === "BEGINNER") {
|
||||
throw new SkipScoreFailure(`BEGINNER scores are not supported.`);
|
||||
}
|
||||
|
||||
const chart = await FindIIDXChartOnInGameID(data.music_id, playtype, data.diff_type);
|
||||
|
||||
if (!chart) {
|
||||
throw new SongOrChartNotFoundFailure(
|
||||
`Could not find chart with musicID ${data.music_id} (${playtype} ${data.diff_type}.)`,
|
||||
importType,
|
||||
data,
|
||||
context
|
||||
);
|
||||
}
|
||||
|
||||
const song = await FindSongOnID("iidx", chart.songID);
|
||||
|
||||
if (!song) {
|
||||
logger.severe(`Could not find song with songID ${chart.songID}, but chart exists for it?`);
|
||||
throw new InternalFailure(`Song-Chart Desync on songID ${chart.songID}`);
|
||||
}
|
||||
|
||||
const lamp = ConvertMERLamp(data.clear_type);
|
||||
|
||||
const timeAchieved = ParseDateFromString(ConvertDateToJST(data.update_time));
|
||||
|
||||
const dryScore: DryScore<"iidx:DP" | "iidx:SP"> = {
|
||||
game: "iidx",
|
||||
comment: null,
|
||||
importType: "file/mer-iidx",
|
||||
service: "MER",
|
||||
scoreData: {
|
||||
score: data.score,
|
||||
lamp,
|
||||
judgements: {},
|
||||
optional: {
|
||||
bp: data.miss_count === -1 ? null : data.miss_count,
|
||||
},
|
||||
},
|
||||
scoreMeta: {},
|
||||
timeAchieved: timeAchieved !== null ? timeAchieved : null,
|
||||
};
|
||||
|
||||
return {
|
||||
chart,
|
||||
song,
|
||||
dryScore,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* MER passes us a rather useless date without any timezone information.
|
||||
* To ensure that this parses properly regardless of timezone, we need to
|
||||
* assert thathere.
|
||||
*
|
||||
* @param uselessDate - A date string like 2021-03-24 07:15:22.
|
||||
* As you can see, it has no timezone information, and is ambiguous.
|
||||
*/
|
||||
function ConvertDateToJST(uselessDate: string) {
|
||||
return `${uselessDate.replace(" ", "T")}+09:00`;
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
import { ParseMerIIDX } from "./parser";
|
||||
import deepmerge from "deepmerge";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import t from "tap";
|
||||
import { MockMulterFile } from "test-utils/mock-multer";
|
||||
import ResetDBState from "test-utils/resets";
|
||||
import { GetKTDataBuffer, GetKTDataJSON } from "test-utils/test-data";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
t.test("#ParseMerIIDX", (t) => {
|
||||
t.beforeEach(ResetDBState);
|
||||
|
||||
function mrfb(buffer: Buffer) {
|
||||
return ParseMerIIDX(MockMulterFile(buffer, "buffer.json"), {}, logger);
|
||||
}
|
||||
|
||||
function mrfj(obj: unknown) {
|
||||
return ParseMerIIDX(
|
||||
MockMulterFile(Buffer.from(JSON.stringify([obj])), "buffer.json"),
|
||||
{},
|
||||
logger
|
||||
);
|
||||
}
|
||||
|
||||
function mrff(filename: string) {
|
||||
return ParseMerIIDX(MockMulterFile(GetKTDataBuffer(filename), filename), {}, logger);
|
||||
}
|
||||
|
||||
t.test("Basic Parsing", (t) => {
|
||||
const res = mrff("./mer/base.json");
|
||||
|
||||
t.hasStrict(
|
||||
res,
|
||||
{
|
||||
game: "iidx",
|
||||
context: {},
|
||||
classProvider: null,
|
||||
iterable: [
|
||||
{
|
||||
music_id: 3007,
|
||||
music_name: "Presto",
|
||||
play_type: "SINGLE",
|
||||
diff_type: "HYPER",
|
||||
score: 566,
|
||||
miss_count: 46,
|
||||
clear_type: "NO PLAY",
|
||||
update_time: "2019-06-01 19:56:59",
|
||||
},
|
||||
{
|
||||
music_id: 3013,
|
||||
music_name: "THE SAFARI",
|
||||
play_type: "SINGLE",
|
||||
diff_type: "NORMAL",
|
||||
score: 681,
|
||||
miss_count: 102,
|
||||
clear_type: "FAILED",
|
||||
update_time: "2019-05-30 03:21:57",
|
||||
},
|
||||
{
|
||||
music_id: 3213,
|
||||
music_name: "TAKE ON ME",
|
||||
play_type: "SINGLE",
|
||||
diff_type: "ANOTHER",
|
||||
score: 922,
|
||||
miss_count: 56,
|
||||
clear_type: "CLEAR",
|
||||
update_time: "2019-05-03 02:10:58",
|
||||
},
|
||||
],
|
||||
},
|
||||
"Should correctly parse data."
|
||||
);
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
const baseScore = {
|
||||
music_id: 3007,
|
||||
version_id: 3,
|
||||
version_name: "3rd style",
|
||||
music_name: "Presto",
|
||||
play_type: "SINGLE",
|
||||
diff_type: "HYPER",
|
||||
score: 566,
|
||||
score_percent: 56.8273,
|
||||
miss_count: 46,
|
||||
grade: "B",
|
||||
clear_type: "NO PLAY",
|
||||
clear_type_id: 0,
|
||||
level: 8,
|
||||
note: 498,
|
||||
play_count: 6,
|
||||
update_time: "2019-06-01 19:56:59",
|
||||
score_diff_str: "B+12",
|
||||
};
|
||||
|
||||
t.test("Should throw on invalid play_type", (t) => {
|
||||
t.throws(() => mrfj(deepmerge(baseScore, { play_type: "INVALID" })));
|
||||
t.throws(() => mrfj(deepmerge(baseScore, { play_type: null })));
|
||||
t.throws(() => mrfj(deepmerge(baseScore, { play_type: undefined })));
|
||||
t.throws(() => mrfj(deepmerge(baseScore, { play_type: 1 })));
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should throw on invalid score", (t) => {
|
||||
t.throws(() => mrfj(deepmerge(baseScore, { score: -1 })));
|
||||
t.throws(() => mrfj(deepmerge(baseScore, { score: 1.5 })));
|
||||
t.throws(() => mrfj(deepmerge(baseScore, { score: "1" })));
|
||||
t.throws(() => mrfj(deepmerge(baseScore, { score: null })));
|
||||
t.throws(() => mrfj(deepmerge(baseScore, { score: undefined })));
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should throw on invalid diff_type", (t) => {
|
||||
t.throws(() => mrfj(deepmerge(baseScore, { diff_type: "INVALID" })));
|
||||
t.throws(() => mrfj(deepmerge(baseScore, { diff_type: null })));
|
||||
t.throws(() => mrfj(deepmerge(baseScore, { diff_type: undefined })));
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should throw on invalid clear_type", (t) => {
|
||||
t.throws(() => mrfj(deepmerge(baseScore, { clear_type: "INVALID" })));
|
||||
t.throws(() => mrfj(deepmerge(baseScore, { clear_type: null })));
|
||||
t.throws(() => mrfj(deepmerge(baseScore, { clear_type: undefined })));
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should throw on invalid miss_count", (t) => {
|
||||
t.throws(() => mrfj(deepmerge(baseScore, { miss_count: "INVALID" })));
|
||||
t.throws(() => mrfj(deepmerge(baseScore, { miss_count: null })));
|
||||
t.throws(() => mrfj(deepmerge(baseScore, { miss_count: undefined })));
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should throw on invalid JSON", (t) => {
|
||||
t.throws(() => mrfb(Buffer.from("{]")));
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should throw on non-top-level-array", (t) => {
|
||||
t.throws(() => mrfb(Buffer.from("{}")));
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should throw on invalid Mer Scores", (t) => {
|
||||
t.throws(() => mrfb(Buffer.from(JSON.stringify([{ foo: "bar" }]))));
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.end();
|
||||
});
|
||||
@@ -1,61 +0,0 @@
|
||||
import ScoreImportFatalError from "../../../framework/score-importing/score-import-error";
|
||||
import { p } from "prudence";
|
||||
import { FormatPrError } from "utils/prudence";
|
||||
import type { ParserFunctionReturns } from "../../common/types";
|
||||
import type { MerScore } from "./types";
|
||||
import type { KtLogger } from "lib/logger/logger";
|
||||
import type { EmptyObject } from "utils/types";
|
||||
|
||||
const PR_MER_IIDX = {
|
||||
music_id: p.isPositiveInteger,
|
||||
play_type: p.isIn("SINGLE", "DOUBLE"),
|
||||
diff_type: p.isIn("NORMAL", "HYPER", "ANOTHER", "LEGGENDARIA", "BEGINNER"),
|
||||
score: p.isPositiveInteger,
|
||||
miss_count: p.or(p.isPositiveInteger, p.is(-1)),
|
||||
clear_type: p.isIn(
|
||||
"NO PLAY",
|
||||
"FAILED",
|
||||
"ASSIST CLEAR",
|
||||
"EASY CLEAR",
|
||||
"CLEAR",
|
||||
"HARD CLEAR",
|
||||
"EX HARD CLEAR",
|
||||
"FULLCOMBO CLEAR"
|
||||
),
|
||||
update_time: "string",
|
||||
};
|
||||
|
||||
export function ParseMerIIDX(
|
||||
fileData: Express.Multer.File,
|
||||
body: Record<string, unknown>,
|
||||
logger: KtLogger
|
||||
): ParserFunctionReturns<MerScore, EmptyObject> {
|
||||
let jsonData;
|
||||
|
||||
try {
|
||||
jsonData = JSON.parse(fileData.buffer.toString("utf-8")) as unknown;
|
||||
} catch (err) {
|
||||
logger.info((err as Error).message);
|
||||
throw new ScoreImportFatalError(400, "Invalid JSON.");
|
||||
}
|
||||
|
||||
if (!Array.isArray(jsonData)) {
|
||||
throw new ScoreImportFatalError(400, `Invalid MER-IIDX JSON: Expected Top-Level Array.`);
|
||||
}
|
||||
|
||||
// this is because prudence doesn't support top level arrays at the moment.
|
||||
for (let i = 0; i < jsonData.length; i++) {
|
||||
const err = p(jsonData[i], PR_MER_IIDX, {}, { allowExcessKeys: true });
|
||||
|
||||
if (err) {
|
||||
throw new ScoreImportFatalError(400, `${FormatPrError(err)} [Index ${i}]`);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
classProvider: null,
|
||||
context: {},
|
||||
iterable: jsonData as Array<MerScore>,
|
||||
game: "iidx",
|
||||
};
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import type { integer } from "tachi-common";
|
||||
|
||||
export interface MerScore {
|
||||
music_id: integer;
|
||||
play_type: "DOUBLE" | "SINGLE";
|
||||
diff_type: "ANOTHER" | "BEGINNER" | "HYPER" | "LEGGENDARIA" | "NORMAL";
|
||||
score: integer;
|
||||
miss_count: integer;
|
||||
clear_type:
|
||||
| "ASSIST CLEAR"
|
||||
| "CLEAR"
|
||||
| "EASY CLEAR"
|
||||
| "EX HARD CLEAR"
|
||||
| "FAILED"
|
||||
| "FULLCOMBO CLEAR"
|
||||
| "HARD CLEAR"
|
||||
| "NO PLAY";
|
||||
update_time: string;
|
||||
}
|
||||
@@ -17,7 +17,6 @@ import {
|
||||
import ParseBatchManual from "./file/batch-manual/parser";
|
||||
import ParseEamusementIIDXCSV from "./file/eamusement-iidx-csv/parser";
|
||||
import ParseEamusementSDVXCSV from "./file/eamusement-sdvx-csv/parser";
|
||||
import { ParseMerIIDX } from "./file/mer-iidx/parser";
|
||||
import ParsePLIIIDXCSV from "./file/pli-iidx-csv/parser";
|
||||
import { ParseSolidStateXML } from "./file/solid-state-squad/parser";
|
||||
import {
|
||||
@@ -37,7 +36,6 @@ import { ParseIRUSC } from "./ir/usc/parser";
|
||||
export const Parsers = {
|
||||
"file/solid-state-squad": ParseSolidStateXML,
|
||||
"file/batch-manual": ParseBatchManual,
|
||||
"file/mer-iidx": ParseMerIIDX,
|
||||
"file/pli-iidx-csv": ParsePLIIIDXCSV,
|
||||
"file/eamusement-iidx-csv": ParseEamusementIIDXCSV,
|
||||
"file/eamusement-sdvx-csv": ParseEamusementSDVXCSV,
|
||||
|
||||
@@ -301,44 +301,6 @@ t.test("POST /api/v1/import/file", async (t) => {
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("file/mer-iidx", (t) => {
|
||||
t.beforeEach(LoadTachiIIDXData);
|
||||
|
||||
t.test("Example Import", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/api/v1/import/file")
|
||||
.set("Cookie", cookie)
|
||||
.attach("scoreData", GetKTDataBuffer("./mer/base.json"), "base.json")
|
||||
.field("importType", "file/mer-iidx");
|
||||
|
||||
t.equal(res.body.success, true, "Should be successful");
|
||||
|
||||
t.equal(res.body.body.errors.length, 0, "Import Should have 0 failed scores.");
|
||||
|
||||
t.equal(res.body.body.scoreIDs.length, 3, "Should have 3 successful scores.");
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Example Import", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/api/v1/import/file")
|
||||
.set("Cookie", cookie)
|
||||
.attach("scoreData", GetKTDataBuffer("./mer/large.json"), "base.json")
|
||||
.field("importType", "file/mer-iidx");
|
||||
|
||||
t.equal(res.body.success, true, "Should be successful");
|
||||
|
||||
t.equal(res.body.body.errors.length, 0, "Import Should have 0 failed scores.");
|
||||
|
||||
t.equal(res.body.body.scoreIDs.length, 627, "Should have 627 successful scores.");
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.skip("file/solid-state-squad", (t) => {
|
||||
t.beforeEach(LoadTachiIIDXData);
|
||||
|
||||
|
||||
@@ -55,7 +55,6 @@
|
||||
"file/eamusement-iidx-csv",
|
||||
"file/batch-manual",
|
||||
"file/solid-state-squad",
|
||||
"file/mer-iidx",
|
||||
"file/pli-iidx-csv",
|
||||
"ir/direct-manual",
|
||||
"ir/barbatos",
|
||||
|
||||
Reference in New Issue
Block a user