mirror of
https://github.com/zkldi/Tachi.git
synced 2026-09-28 18:08:15 +03:00
Finally, Add tests and linting!
This commit is contained in:
@@ -6,4 +6,6 @@ scripts/single-time
|
||||
|
||||
.vs
|
||||
|
||||
scripts/rerunners/bpi-output.json
|
||||
scripts/rerunners/bpi-output.json
|
||||
|
||||
failed-tests.log
|
||||
+186097
-46524
File diff suppressed because it is too large
Load Diff
@@ -3332,6 +3332,7 @@
|
||||
"game": "bms",
|
||||
"inactive": false,
|
||||
"playtype": "7K",
|
||||
"searchTerms": [],
|
||||
"title": "Insane",
|
||||
"type": "charts"
|
||||
},
|
||||
@@ -3343,6 +3344,7 @@
|
||||
"game": "bms",
|
||||
"inactive": false,
|
||||
"playtype": "7K",
|
||||
"searchTerms": [],
|
||||
"title": "Insane 2",
|
||||
"type": "charts"
|
||||
},
|
||||
@@ -3354,6 +3356,7 @@
|
||||
"game": "bms",
|
||||
"inactive": false,
|
||||
"playtype": "7K",
|
||||
"searchTerms": [],
|
||||
"title": "LN",
|
||||
"type": "charts"
|
||||
},
|
||||
@@ -3365,6 +3368,7 @@
|
||||
"game": "bms",
|
||||
"inactive": false,
|
||||
"playtype": "7K",
|
||||
"searchTerms": [],
|
||||
"title": "Normal",
|
||||
"type": "charts"
|
||||
},
|
||||
@@ -3376,6 +3380,7 @@
|
||||
"game": "bms",
|
||||
"inactive": false,
|
||||
"playtype": "7K",
|
||||
"searchTerms": [],
|
||||
"title": "Normal 2",
|
||||
"type": "charts"
|
||||
},
|
||||
@@ -3387,6 +3392,7 @@
|
||||
"game": "bms",
|
||||
"inactive": false,
|
||||
"playtype": "7K",
|
||||
"searchTerms": [],
|
||||
"title": "Overjoy",
|
||||
"type": "charts"
|
||||
},
|
||||
@@ -3398,6 +3404,7 @@
|
||||
"game": "bms",
|
||||
"inactive": false,
|
||||
"playtype": "7K",
|
||||
"searchTerms": [],
|
||||
"title": "Satellite",
|
||||
"type": "charts"
|
||||
},
|
||||
@@ -3409,6 +3416,7 @@
|
||||
"game": "bms",
|
||||
"inactive": false,
|
||||
"playtype": "7K",
|
||||
"searchTerms": [],
|
||||
"title": "Scratch 3rd",
|
||||
"type": "charts"
|
||||
},
|
||||
@@ -3914,6 +3922,7 @@
|
||||
"game": "bms",
|
||||
"inactive": false,
|
||||
"playtype": "7K",
|
||||
"searchTerms": [],
|
||||
"title": "Stella",
|
||||
"type": "charts"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
js
|
||||
@@ -0,0 +1,92 @@
|
||||
{
|
||||
"root": true,
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint",
|
||||
"import"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaVersion": 2020
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:prettier/recommended",
|
||||
"plugin:import/typescript",
|
||||
"plugin:import/warnings",
|
||||
"plugin:import/errors"
|
||||
],
|
||||
"rules": {
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{
|
||||
"printWidth": 100,
|
||||
"tabWidth": 4,
|
||||
"semi": true,
|
||||
"singleQuote": false,
|
||||
"trailingComma": "es5",
|
||||
"bracketSpacing": true,
|
||||
"endOfLine": "auto",
|
||||
"useTabs": true
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"warn",
|
||||
{
|
||||
"argsIgnorePattern": "logger"
|
||||
}
|
||||
],
|
||||
"require-await": "warn",
|
||||
"no-await-in-loop": "warn",
|
||||
"no-unused-labels": "error",
|
||||
"prefer-const": "error",
|
||||
"eqeqeq": "error",
|
||||
"no-eval": "error",
|
||||
"no-var": "error",
|
||||
"no-new-object": "error",
|
||||
"quote-props": [
|
||||
"error",
|
||||
"as-needed"
|
||||
],
|
||||
"no-array-constructor": "error",
|
||||
"prefer-template": "error",
|
||||
"prefer-promise-reject-errors": "error",
|
||||
"no-useless-escape": "error",
|
||||
"no-loop-func": "error",
|
||||
"prefer-rest-params": "error",
|
||||
"default-param-last": "error",
|
||||
"no-new-func": "error",
|
||||
"arrow-body-style": "error",
|
||||
"no-useless-constructor": "error",
|
||||
"no-duplicate-imports": "error",
|
||||
"dot-notation": "error",
|
||||
"space-before-blocks": "error",
|
||||
"no-prototype-builtins": "off",
|
||||
"prefer-arrow-callback": "error",
|
||||
"curly": "error",
|
||||
"no-template-curly-in-string": "error",
|
||||
"no-implied-eval": "error",
|
||||
"yoda": "error",
|
||||
"no-labels": "error",
|
||||
"no-useless-concat": "error",
|
||||
"radix": "error",
|
||||
"no-octal-escape": "error",
|
||||
"no-param-reassign": "error",
|
||||
"no-proto": "error",
|
||||
"no-return-await": "error",
|
||||
"no-throw-literal": "error",
|
||||
"no-unmodified-loop-condition": "error",
|
||||
"no-unused-expressions": "error",
|
||||
"no-useless-call": "error",
|
||||
"no-useless-return": "error",
|
||||
"require-unicode-regexp": "error"
|
||||
}
|
||||
}
|
||||
@@ -66,20 +66,16 @@ function DeterministicCollectionSort() {
|
||||
|
||||
if (collection.startsWith("charts-")) {
|
||||
content.sort(ChartSort);
|
||||
}
|
||||
else if (collection.startsWith("songs-")) {
|
||||
} else if (collection.startsWith("songs-")) {
|
||||
content.sort((a, b) => a.id - b.id);
|
||||
}
|
||||
else if (collection.startsWith("folders")) {
|
||||
} else if (collection.startsWith("folders")) {
|
||||
content.sort(FolderSort);
|
||||
}
|
||||
else if (collection.startsWith("tables")) {
|
||||
} else if (collection.startsWith("tables")) {
|
||||
content.sort(TableSort);
|
||||
} else if (collection.startsWith("bms-course-lookup.json")) {
|
||||
content.sort(BMSCourseSort);
|
||||
}
|
||||
|
||||
|
||||
content = content.map(SortObjectKeys);
|
||||
|
||||
fs.writeFileSync(collPath, JSON.stringify(content, null, "\t"));
|
||||
@@ -87,7 +83,7 @@ function DeterministicCollectionSort() {
|
||||
}
|
||||
|
||||
function SortObjectKeys(object) {
|
||||
let newObject = {};
|
||||
const newObject = {};
|
||||
|
||||
for (const key of Object.keys(object).sort()) {
|
||||
let v = object[key];
|
||||
@@ -106,4 +102,4 @@ if (require.main === module) {
|
||||
DeterministicCollectionSort();
|
||||
}
|
||||
|
||||
module.exports = DeterministicCollectionSort
|
||||
module.exports = DeterministicCollectionSort;
|
||||
|
||||
@@ -31,16 +31,14 @@ const collections = [];
|
||||
|
||||
if (options.all) {
|
||||
collections.push("folders", "tables");
|
||||
collections.push(...StaticConfig.allSupportedGames.map(e => `songs-${e}`));
|
||||
collections.push(...StaticConfig.allSupportedGames.map(e => `charts-${e}`));
|
||||
collections.push(...StaticConfig.allSupportedGames.map((e) => `songs-${e}`));
|
||||
collections.push(...StaticConfig.allSupportedGames.map((e) => `charts-${e}`));
|
||||
} else if (program.args[0]) {
|
||||
collections.push(program.args[0]);
|
||||
}
|
||||
|
||||
// Add the songs-{game} and charts-{game} collections.
|
||||
|
||||
|
||||
|
||||
(async () => {
|
||||
logger.info(`Exporting ${collections.length} collections.`);
|
||||
|
||||
@@ -67,4 +65,4 @@ async function ExportCollection(collection) {
|
||||
fs.writeFileSync(pt, JSON.stringify(data, null, options.useTabs ? "\t" : undefined));
|
||||
|
||||
logger.info(`Wrote to ${pt}.`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
function FindChartWithPTDFVersion(collection, songID, playtype, difficulty, version) {
|
||||
return collection.find(chart => chart.songID === songID && chart.playtype === playtype && chart.difficulty === difficulty && chart.versions.includes(version));
|
||||
return collection.find(
|
||||
(chart) =>
|
||||
chart.songID === songID &&
|
||||
chart.playtype === playtype &&
|
||||
chart.difficulty === difficulty &&
|
||||
chart.versions.includes(version)
|
||||
);
|
||||
}
|
||||
|
||||
function FindSongWithTitle(collection, title) {
|
||||
return collection.find(e => e.title === title || e.altTitles.includes(title));
|
||||
return collection.find((e) => e.title === title || e.altTitles.includes(title));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
FindSongWithTitle,
|
||||
FindChartWithPTDFVersion,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -14,8 +14,7 @@ const logger = require("./logger");
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program
|
||||
.option("-d, --db <Database Name>")
|
||||
program.option("-d, --db <Database Name>");
|
||||
|
||||
program.parse(process.argv);
|
||||
const options = program.opts();
|
||||
@@ -46,4 +45,4 @@ for (const file of fs.readdirSync(base)) {
|
||||
} catch (err) {
|
||||
logger.error(`Failed to import ${file}.`, { command, err });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
const { CreateLogger } = require("mei-logger");
|
||||
|
||||
module.exports = CreateLogger("tachi-database-seed-scripts");
|
||||
module.exports = CreateLogger("tachi-database-seed-scripts");
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
const { MutateCollection, EfficientInPlaceDeepmerge } = require("./util");
|
||||
const deepmerge = require("deepmerge");
|
||||
|
||||
function DoesMatchCriteria(element, mutation) {
|
||||
for (const [key, value] of Object.entries(mutation.match)) {
|
||||
@@ -26,5 +25,5 @@ function ApplyMutations(name, mutations) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ApplyMutations
|
||||
}
|
||||
ApplyMutations,
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"description": "Scripts for dealing with tachi-database-seeds.",
|
||||
"main": "",
|
||||
"scripts": {
|
||||
"test": "tap"
|
||||
"test": "./run-tests.sh"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -23,6 +23,8 @@
|
||||
},
|
||||
"homepage": "https://github.com/TeamNewGuys/tachi-database-seeds#readme",
|
||||
"dependencies": {
|
||||
"@types/node": "^17.0.13",
|
||||
"chalk": "4",
|
||||
"commander": "^8.2.0",
|
||||
"csv-parse": "^5.0.3",
|
||||
"deepmerge": "^4.2.2",
|
||||
@@ -30,7 +32,19 @@
|
||||
"glob": "^7.2.0",
|
||||
"mei-logger": "^1.0.1",
|
||||
"monk": "^7.3.4",
|
||||
"tachi-common": "0.2.43",
|
||||
"prudence": "^0.9.7",
|
||||
"tachi-common": "0.5.12",
|
||||
"ts-node": "^10.4.0",
|
||||
"xml2js": "^0.4.23"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^5.10.2",
|
||||
"@typescript-eslint/parser": "^5.10.2",
|
||||
"eslint": "^8.8.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"prettier": "^2.5.1",
|
||||
"typescript": "^4.5.5"
|
||||
}
|
||||
}
|
||||
Generated
+1204
-281
File diff suppressed because it is too large
Load Diff
@@ -15,5 +15,5 @@ if (require.main === module) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
RemoveUnderscoreID
|
||||
}
|
||||
RemoveUnderscoreID,
|
||||
};
|
||||
|
||||
@@ -79,8 +79,8 @@ for (const info of data.entries.music) {
|
||||
hash,
|
||||
notes,
|
||||
playtype,
|
||||
difficulty
|
||||
})
|
||||
difficulty,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,11 @@ MutateCollection("charts-iidx.json", (charts) => {
|
||||
}
|
||||
match = true;
|
||||
break;
|
||||
} else if (Array.isArray(chart.data.inGameID) ? chart.data.inGameID.includes(data.id) : chart.data.inGameID === data.id) {
|
||||
} else if (
|
||||
Array.isArray(chart.data.inGameID)
|
||||
? chart.data.inGameID.includes(data.id)
|
||||
: chart.data.inGameID === data.id
|
||||
) {
|
||||
existingReference = chart;
|
||||
}
|
||||
}
|
||||
@@ -107,28 +111,26 @@ MutateCollection("charts-iidx.json", (charts) => {
|
||||
}
|
||||
|
||||
charts.push({
|
||||
"chartID": CreateChartID(),
|
||||
"data": {
|
||||
chartID: CreateChartID(),
|
||||
data: {
|
||||
"2dxtraSet": options.name,
|
||||
"arcChartID": null,
|
||||
"hashSHA256": data.hash,
|
||||
"inGameID": data.id,
|
||||
"notecount": data.notes
|
||||
arcChartID: null,
|
||||
hashSHA256: data.hash,
|
||||
inGameID: data.id,
|
||||
notecount: data.notes,
|
||||
},
|
||||
"difficulty": `${options.name} ${data.difficulty}`,
|
||||
"isPrimary": true,
|
||||
"level": "?",
|
||||
"levelNum": 0,
|
||||
difficulty: `${options.name} ${data.difficulty}`,
|
||||
isPrimary: true,
|
||||
level: "?",
|
||||
levelNum: 0,
|
||||
playtype: data.playtype,
|
||||
"rgcID": null,
|
||||
"songID": existingReference.songID,
|
||||
"tierlistInfo": {},
|
||||
"versions": [
|
||||
options.version
|
||||
]
|
||||
rgcID: null,
|
||||
songID: existingReference.songID,
|
||||
tierlistInfo: {},
|
||||
versions: [options.version],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return charts;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12,11 +12,11 @@ module.exports = function AddLevelVersionFolders(name, game, playtypes, version,
|
||||
type: "charts",
|
||||
data: {
|
||||
level,
|
||||
versions: version
|
||||
versions: version,
|
||||
},
|
||||
inactive: false,
|
||||
searchTerms: [],
|
||||
}
|
||||
};
|
||||
|
||||
for (const playtype of playtypes) {
|
||||
const folderID = CreateFolderID(folder.data, folder.game, playtype);
|
||||
@@ -42,19 +42,16 @@ module.exports = function AddLevelVersionFolders(name, game, playtypes, version,
|
||||
tableID: `${game}-${playtype}-${version}-levels`,
|
||||
name: `${FormatGame(game, playtype)} (${name})`,
|
||||
description: `Levels for ${FormatGame(game, playtype)} in ${name}.`,
|
||||
folders: ptFolders[playtype].map(e => e.folderID),
|
||||
folders: ptFolders[playtype].map((e) => e.folderID),
|
||||
game,
|
||||
playtype,
|
||||
inactive: false,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return tables;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
// usage:
|
||||
|
||||
@@ -63,4 +60,4 @@ module.exports = function AddLevelVersionFolders(name, game, playtypes, version,
|
||||
// levels.push(i.toString())
|
||||
// }
|
||||
//
|
||||
// addLevelVersionFolders("CastHour", "iidx", ["SP", "DP"], "29", levels);
|
||||
// addLevelVersionFolders("CastHour", "iidx", ["SP", "DP"], "29", levels);
|
||||
|
||||
@@ -14,7 +14,12 @@ program
|
||||
program.parse(process.argv);
|
||||
const options = program.opts();
|
||||
|
||||
if (!options.course || !["7K", "14K"].includes(options.playtype) || !options.set || Number.isNaN(Number(options.index))) {
|
||||
if (
|
||||
!options.course ||
|
||||
!["7K", "14K"].includes(options.playtype) ||
|
||||
!options.set ||
|
||||
Number.isNaN(Number(options.index))
|
||||
) {
|
||||
throw new Error(`Missing parameters.`);
|
||||
}
|
||||
|
||||
@@ -23,7 +28,7 @@ const parser = new XMLParser();
|
||||
const data = parser.parse(fs.readFileSync(options.course));
|
||||
|
||||
MutateCollection("bms-course-lookup.json", (courses) => {
|
||||
let existingCourses = new Set(courses.map(e => e.md5sums));
|
||||
const existingCourses = new Set(courses.map((e) => e.md5sums));
|
||||
|
||||
let i = 0;
|
||||
for (const d of data.courselist.course) {
|
||||
@@ -37,11 +42,11 @@ MutateCollection("bms-course-lookup.json", (courses) => {
|
||||
md5sums,
|
||||
set: options.set,
|
||||
playtype: options.playtype,
|
||||
value: Number(options.index) + i
|
||||
value: Number(options.index) + i,
|
||||
});
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return courses;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,12 +7,8 @@ const { ReadCollection } = require("../../util");
|
||||
|
||||
const songs = ReadCollection("songs-iidx.json");
|
||||
|
||||
async function parseKr(
|
||||
file,
|
||||
mode,
|
||||
catVals
|
||||
) {
|
||||
let charts = ReadCollection("charts-iidx.json");
|
||||
async function parseKr(file, mode, catVals) {
|
||||
const charts = ReadCollection("charts-iidx.json");
|
||||
|
||||
const krdata = JSON.parse(fs.readFileSync(path.join(__dirname, file), "utf-8"));
|
||||
const mutations = [];
|
||||
@@ -73,10 +69,10 @@ async function parseKr(
|
||||
text: cv.text,
|
||||
value: cv.value,
|
||||
individualDifference: cv.idv,
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
console.log(`Updated ${chart.chartID} to value ${cv.value}.`);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
const { MutateCollection } = require("../util");
|
||||
|
||||
module.exports = (idSet) => {
|
||||
return MutateCollection("charts-iidx.json", (charts) => {
|
||||
module.exports = (idSet) =>
|
||||
MutateCollection("charts-iidx.json", (charts) => {
|
||||
for (const chart of charts) {
|
||||
if (idSet.includes(chart.data.inGameID) && !chart.versions.includes("inf") && chart.data["2dxtraSet"] === null && chart.difficulty !== "LEGGENDARIA" && chart.difficulty !== "BEGINNER") {
|
||||
if (
|
||||
idSet.includes(chart.data.inGameID) &&
|
||||
!chart.versions.includes("inf") &&
|
||||
chart.data["2dxtraSet"] === null &&
|
||||
chart.difficulty !== "LEGGENDARIA" &&
|
||||
chart.difficulty !== "BEGINNER"
|
||||
) {
|
||||
chart.versions.push("inf");
|
||||
}
|
||||
}
|
||||
|
||||
return charts;
|
||||
});
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -5,8 +5,7 @@ const { CreateChartID } = require("../util");
|
||||
const path = require("path");
|
||||
|
||||
const program = new Command();
|
||||
program
|
||||
.option("-f, --file <mxb-json>")
|
||||
program.option("-f, --file <mxb-json>");
|
||||
|
||||
program.parse(process.argv);
|
||||
const options = program.opts();
|
||||
@@ -17,15 +16,15 @@ if (!options.file) {
|
||||
|
||||
let data = JSON.parse(fs.readFileSync(options.file));
|
||||
|
||||
data = data.filter(e => e != null);
|
||||
data = data.filter((e) => e !== null);
|
||||
|
||||
const songs = [];
|
||||
const charts = [];
|
||||
|
||||
let songID = 1;
|
||||
for (const song of data) {
|
||||
const isUpper = song.charts.some(k => k !== null && k.filename.startsWith("exx"));
|
||||
const isUra = song.charts.some(k => k !== null && k.filename.endsWith("_ura2"));
|
||||
const isUpper = song.charts.some((k) => k !== null && k.filename.startsWith("exx"));
|
||||
const isUra = song.charts.some((k) => k !== null && k.filename.endsWith("_ura2"));
|
||||
|
||||
let title = isUpper ? `${song.title} (UPPER)` : song.title;
|
||||
title = isUra ? `${title} (URA)` : title;
|
||||
@@ -38,9 +37,9 @@ for (const song of data) {
|
||||
altTitles: [],
|
||||
data: {
|
||||
displayVersion: null,
|
||||
genre: song.genre
|
||||
genre: song.genre,
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
for (const [index, chart] of Object.entries(song.charts)) {
|
||||
if (chart === null) {
|
||||
@@ -55,7 +54,10 @@ for (const song of data) {
|
||||
songID,
|
||||
chartID: CreateChartID(),
|
||||
// Turns HYPER into Hyper, but keeps EX the same.
|
||||
difficulty: chart.difficulty === "EX" ? "EX" : chart.difficulty[0] + chart.difficulty.slice(1).toLowerCase(),
|
||||
difficulty:
|
||||
chart.difficulty === "EX"
|
||||
? "EX"
|
||||
: chart.difficulty[0] + chart.difficulty.slice(1).toLowerCase(),
|
||||
playtype: "9B",
|
||||
level: chart.level.toString(),
|
||||
levelNum: chart.level,
|
||||
@@ -66,7 +68,7 @@ for (const song of data) {
|
||||
inGameID: index,
|
||||
},
|
||||
tierlistInfo: {},
|
||||
versions: ["peace"]
|
||||
versions: ["peace"],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -74,4 +76,7 @@ for (const song of data) {
|
||||
}
|
||||
|
||||
// fs.writeFileSync(path.join(__dirname, "../../collections/charts-popn.json"), JSON.stringify(charts, null, "\t"));
|
||||
fs.writeFileSync(path.join(__dirname, "../../collections/songs-popn.json"), JSON.stringify(songs, null, "\t"));
|
||||
fs.writeFileSync(
|
||||
path.join(__dirname, "../../collections/songs-popn.json"),
|
||||
JSON.stringify(songs, null, "\t")
|
||||
);
|
||||
|
||||
@@ -10,8 +10,7 @@ const logger = require("../logger");
|
||||
const program = new Command();
|
||||
|
||||
// https://github.com/shimmand/waccaSupportTools/blob/main/analyzePlayData/chartsTable.csv
|
||||
program
|
||||
.option("-f, --file <wacca.csv>")
|
||||
program.option("-f, --file <wacca.csv>");
|
||||
|
||||
program.parse(process.argv);
|
||||
const options = program.opts();
|
||||
@@ -51,7 +50,6 @@ const STARTS = {
|
||||
reverse: Date.parse("2021-8-10"),
|
||||
};
|
||||
|
||||
|
||||
(async () => {
|
||||
const datum = await fetch("https://wacca.marv.jp/music/search.php", {
|
||||
method: "POST",
|
||||
@@ -59,7 +57,7 @@ const STARTS = {
|
||||
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
},
|
||||
body: "cat=all",
|
||||
}).then(r => r.json());
|
||||
}).then((r) => r.json());
|
||||
|
||||
const songs = [];
|
||||
const charts = [];
|
||||
@@ -75,7 +73,7 @@ const STARTS = {
|
||||
prettiedTitle = "13 Donkeys";
|
||||
}
|
||||
|
||||
let time = Date.parse(data.release_date);
|
||||
const time = Date.parse(data.release_date);
|
||||
let ver;
|
||||
|
||||
if (time < STARTS.s) {
|
||||
@@ -97,7 +95,13 @@ const STARTS = {
|
||||
const record = dataMap.get(prettiedTitle);
|
||||
|
||||
if (!record) {
|
||||
logger.warn(`Can't find record with title ${prettiedTitle}. Dumping potentially similar titles.\n${[...dataMap.keys()].filter(e => e.startsWith(prettiedTitle[0])).join("\n")}`);
|
||||
logger.warn(
|
||||
`Can't find record with title ${prettiedTitle}. Dumping potentially similar titles.\n${[
|
||||
...dataMap.keys(),
|
||||
]
|
||||
.filter((e) => e.startsWith(prettiedTitle[0]))
|
||||
.join("\n")}`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -111,15 +115,15 @@ const STARTS = {
|
||||
titleJP: data.title.ruby,
|
||||
artistJP: data.artist.ruby,
|
||||
genre: data.category,
|
||||
displayVersion: ver
|
||||
}
|
||||
displayVersion: ver,
|
||||
},
|
||||
});
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
let diff = record[1 + i * 3];
|
||||
let [diffName, level] = diff.split(" ");
|
||||
let levelNum = Number(record[2 + i * 3]);
|
||||
let isNew = record[3 + i * 3];
|
||||
const diff = record[1 + i * 3];
|
||||
const [diffName, level] = diff.split(" ");
|
||||
const levelNum = Number(record[2 + i * 3]);
|
||||
const isNew = record[3 + i * 3];
|
||||
|
||||
if (!levelNum) {
|
||||
continue;
|
||||
@@ -135,17 +139,22 @@ const STARTS = {
|
||||
difficulty: diffName,
|
||||
playtype: "Single",
|
||||
data: {
|
||||
isHot: isNew === "true"
|
||||
isHot: isNew === "true",
|
||||
},
|
||||
tierlistInfo: {},
|
||||
versions: ["reverse"]
|
||||
versions: ["reverse"],
|
||||
});
|
||||
}
|
||||
|
||||
songID++;
|
||||
}
|
||||
|
||||
fs.writeFileSync(path.resolve(__dirname, "../../collections/charts-wacca.json"), JSON.stringify(charts, null, "\t"));
|
||||
fs.writeFileSync(path.resolve(__dirname, "../../collections/songs-wacca.json"), JSON.stringify(songs, null, "\t"));
|
||||
|
||||
})();
|
||||
fs.writeFileSync(
|
||||
path.resolve(__dirname, "../../collections/charts-wacca.json"),
|
||||
JSON.stringify(charts, null, "\t")
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.resolve(__dirname, "../../collections/songs-wacca.json"),
|
||||
JSON.stringify(songs, null, "\t")
|
||||
);
|
||||
})();
|
||||
|
||||
@@ -56,12 +56,7 @@ async function UpdatePoyashiData() {
|
||||
continue;
|
||||
}
|
||||
|
||||
const tachiChart = (await FindChartWithPTDFVersion(
|
||||
tachiSong.id,
|
||||
playtype,
|
||||
diff,
|
||||
"29"
|
||||
));
|
||||
const tachiChart = await FindChartWithPTDFVersion(tachiSong.id, playtype, diff, "29");
|
||||
|
||||
if (!tachiChart) {
|
||||
logger.warn(
|
||||
@@ -89,9 +84,7 @@ async function UpdatePoyashiData() {
|
||||
tachiChart.data.worldRecord = Number(d.wr);
|
||||
}
|
||||
|
||||
MutateCollection("charts-iidx.json", () => {
|
||||
return chartData;
|
||||
});
|
||||
MutateCollection("charts-iidx.json", () => chartData);
|
||||
|
||||
logger.info(`Done.`);
|
||||
}
|
||||
@@ -111,7 +104,12 @@ function FindSongOnTitle(title) {
|
||||
|
||||
function FindChartWithPTDFVersion(songID, playtype, diff, version) {
|
||||
for (const chart of chartData) {
|
||||
if (chart.songID === songID && chart.playtype === playtype && chart.difficulty === diff && chart.versions.includes(version)) {
|
||||
if (
|
||||
chart.songID === songID &&
|
||||
chart.playtype === playtype &&
|
||||
chart.difficulty === diff &&
|
||||
chart.versions.includes(version)
|
||||
) {
|
||||
return chart;
|
||||
}
|
||||
}
|
||||
|
||||
Executable
+12
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Output stderr and stdout to the terminal, but only save stderr to a file
|
||||
# Isn't bash wonderful?
|
||||
|
||||
# I can't figure out how to make it write to failed-tests.log instead of appending
|
||||
# so, whatever.
|
||||
# look. I don't like bash much.
|
||||
# I'd rather spend 0% of my time here.
|
||||
rm failed-tests.log -f
|
||||
|
||||
ts-node test/collections.test.ts 2> >(tee -a failed-tests.log >&2)
|
||||
@@ -0,0 +1,98 @@
|
||||
import chalk from "chalk";
|
||||
import { writeFileSync } from "fs";
|
||||
import { ReadCollection } from "../util";
|
||||
import { SCHEMAS } from "./schemas";
|
||||
|
||||
function FormatPrError(err, foreword = "Error") {
|
||||
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}.`;
|
||||
}
|
||||
|
||||
const songFormat = (s) => `${s.artist} - ${s.title} (${s.id})`;
|
||||
const chartFormat = (s) => `${s.id} - ${s.playtype} ${s.difficulty} (${s.chartID})`;
|
||||
|
||||
const FormatFunctions: Record<keyof typeof SCHEMAS, (d) => string> = {
|
||||
"bms-course-lookup": (d) => d.title,
|
||||
folders: (d) => d.title,
|
||||
tables: (d) => d.name,
|
||||
"songs-bms": songFormat,
|
||||
"songs-chunithm": songFormat,
|
||||
// "songs-ddr": songFormat,
|
||||
// "songs-gitadora": songFormat,
|
||||
"songs-iidx": songFormat,
|
||||
"songs-jubeat": songFormat,
|
||||
// "songs-maimai": songFormat,
|
||||
"songs-museca": songFormat,
|
||||
"songs-pms": songFormat,
|
||||
"songs-popn": songFormat,
|
||||
"songs-sdvx": songFormat,
|
||||
"songs-usc": songFormat,
|
||||
"songs-wacca": songFormat,
|
||||
"charts-bms": chartFormat,
|
||||
"charts-chunithm": chartFormat,
|
||||
// "charts-ddr": chartFormat,
|
||||
// "charts-gitadora": chartFormat,
|
||||
"charts-iidx": chartFormat,
|
||||
"charts-jubeat": chartFormat,
|
||||
// "charts-maimai": chartFormat,
|
||||
"charts-museca": chartFormat,
|
||||
"charts-pms": chartFormat,
|
||||
"charts-popn": chartFormat,
|
||||
"charts-sdvx": chartFormat,
|
||||
"charts-usc": chartFormat,
|
||||
"charts-wacca": chartFormat,
|
||||
};
|
||||
|
||||
let exitCode = 0;
|
||||
const suites = [];
|
||||
|
||||
for (const [collection, validator] of Object.entries(SCHEMAS)) {
|
||||
console.log(`[VALIDATING] ${collection}`);
|
||||
|
||||
let success = 0;
|
||||
let fails = 0;
|
||||
|
||||
const collectionName = `${collection}.json`;
|
||||
const formatFn = FormatFunctions[collection];
|
||||
|
||||
const data = ReadCollection(collectionName, true);
|
||||
|
||||
for (const d of data) {
|
||||
const pretty = formatFn(d);
|
||||
|
||||
try {
|
||||
validator(d);
|
||||
|
||||
success++;
|
||||
} catch (err) {
|
||||
console.error(
|
||||
chalk.red(`[ERR] ${collectionName} | ${pretty} | ${FormatPrError(err)}.`)
|
||||
);
|
||||
fails++;
|
||||
}
|
||||
}
|
||||
|
||||
const report = `GOOD: ${success}, BAD: ${fails}(${Math.min(
|
||||
(success * 100) / fails,
|
||||
100
|
||||
).toFixed(2)}%)`;
|
||||
if (fails > 0) {
|
||||
console.error(chalk.red(`[FAILED] ${collection}. ${report}.`));
|
||||
exitCode++;
|
||||
} else {
|
||||
console.log(chalk.green(`[GOOD] ${collection}. ${report}.`));
|
||||
}
|
||||
|
||||
suites.push({ name: collection, report, good: fails === 0 });
|
||||
}
|
||||
|
||||
console.log(`=== Suite Overview ===`);
|
||||
for (const suite of suites) {
|
||||
console.log(chalk[suite.good ? "green" : "red"](`${suite.name}: ${suite.report}`));
|
||||
}
|
||||
|
||||
process.exit(exitCode);
|
||||
@@ -0,0 +1,346 @@
|
||||
import p, { PrudenceSchema } from "prudence";
|
||||
import { Game, Playtypes, GetGamePTConfig, GetGameConfig } from "tachi-common";
|
||||
import { allSupportedGames } from "tachi-common/js/config/static-config";
|
||||
|
||||
function prSchemaify(schema: PrudenceSchema) {
|
||||
return (s: unknown): true => {
|
||||
const err = p(s, schema);
|
||||
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
function IsValidPlaytype(game: Game, str: string): str is Playtypes[Game] {
|
||||
return GetGameConfig(game).validPlaytypes.includes(str as Playtypes[Game]);
|
||||
}
|
||||
|
||||
function IsValidGame(str: string): str is Game {
|
||||
return allSupportedGames.includes(str as Game);
|
||||
}
|
||||
|
||||
const getPlaytype = (game: Game, self: unknown): Playtypes[Game] => {
|
||||
if (!self || typeof self !== "object") {
|
||||
throw new Error("Expected an object.");
|
||||
}
|
||||
|
||||
const gameConfig = GetGameConfig(game);
|
||||
|
||||
const s = self as Record<string, unknown>;
|
||||
|
||||
const playtype = s.playtype as string;
|
||||
if (!IsValidPlaytype(game, playtype)) {
|
||||
throw new Error(`Expected any of ${gameConfig.validPlaytypes.join(", ")}`);
|
||||
}
|
||||
|
||||
return playtype;
|
||||
};
|
||||
|
||||
const games = allSupportedGames;
|
||||
|
||||
const isValidPlaytype = (self: unknown, parent: Record<string, unknown>) => {
|
||||
if (!parent.game || typeof parent.game !== "string" || !IsValidGame(parent.game)) {
|
||||
throw new Error(`Invalid Schema, need game to base IsValidPlaytype off of.`);
|
||||
}
|
||||
|
||||
if (typeof self !== "string") {
|
||||
return "Expected a string.";
|
||||
}
|
||||
|
||||
if (!IsValidPlaytype(parent.game, self)) {
|
||||
return `Expected a valid playtype for ${parent.game}`;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const PR_SongDocument = (data: PrudenceSchema): PrudenceSchema => ({
|
||||
id: p.isPositiveInteger,
|
||||
title: "string",
|
||||
artist: "string",
|
||||
searchTerms: ["string"],
|
||||
altTitles: ["string"],
|
||||
data,
|
||||
});
|
||||
|
||||
const PR_ChartDocument = (
|
||||
game: Game,
|
||||
playtype: Playtypes[Game],
|
||||
data: PrudenceSchema
|
||||
): PrudenceSchema => {
|
||||
const gptConfig = GetGamePTConfig(game, playtype);
|
||||
|
||||
return {
|
||||
songID: p.isPositiveInteger,
|
||||
chartID: "string",
|
||||
rgcID: "?string",
|
||||
level: "string",
|
||||
levelNum: "number",
|
||||
isPrimary: "boolean",
|
||||
difficulty: p.isIn(gptConfig.difficulties),
|
||||
playtype: p.is(playtype),
|
||||
data,
|
||||
tierlistInfo: Object.fromEntries(
|
||||
gptConfig.tierlists.map((t) => [
|
||||
t,
|
||||
p.optional({ text: "string", value: "number", individualDifference: "*boolean" }),
|
||||
])
|
||||
),
|
||||
versions: [p.isIn(gptConfig.supportedVersions)],
|
||||
};
|
||||
};
|
||||
|
||||
export const SCHEMAS = {
|
||||
"bms-course-lookup": prSchemaify({
|
||||
title: "string",
|
||||
// Must be comprised of 4 md5 hashes, which are 32 chars long.
|
||||
md5sums: (self) => {
|
||||
if (typeof self !== "string") {
|
||||
return "Expected a string";
|
||||
}
|
||||
|
||||
if (self.length !== 32 * 4) {
|
||||
return "Expected 32 * 4 characters (4 md5 hashes long).";
|
||||
}
|
||||
|
||||
if (!self.match(/^[a-z0-9]*$/u)) {
|
||||
return "Expected all chars to be in the range of a-z0-9.";
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
set: p.isIn("genocideDan", "stslDan"),
|
||||
playtype: p.isIn("7K", "14K"),
|
||||
value: p.isInteger,
|
||||
}),
|
||||
folders: prSchemaify({
|
||||
title: "string",
|
||||
game: p.isIn(games),
|
||||
playtype: isValidPlaytype,
|
||||
folderID: "string",
|
||||
inactive: "boolean",
|
||||
searchTerms: ["string"],
|
||||
type: p.isIn("songs", "charts", "static"),
|
||||
data: (self, parent) => {
|
||||
if (parent.type === "songs") {
|
||||
return true; //temp. should be a song.
|
||||
} else if (parent.type === "charts") {
|
||||
return true; //temp. should be a chart.
|
||||
}
|
||||
|
||||
return (
|
||||
(Array.isArray(self) && self.every((r) => typeof r === "string")) ||
|
||||
"Expected an array of only strings."
|
||||
);
|
||||
},
|
||||
}),
|
||||
tables: prSchemaify({
|
||||
tableID: "string",
|
||||
game: p.isIn(games),
|
||||
playtype: isValidPlaytype,
|
||||
title: "string",
|
||||
default: "boolean",
|
||||
description: "string",
|
||||
folders: ["string"],
|
||||
inactive: "boolean",
|
||||
}),
|
||||
"songs-bms": prSchemaify(
|
||||
PR_SongDocument({
|
||||
genre: "?string",
|
||||
subtitle: "?string",
|
||||
subartist: "?string",
|
||||
tableString: "?string",
|
||||
})
|
||||
),
|
||||
"songs-chunithm": prSchemaify(
|
||||
PR_SongDocument({
|
||||
genre: "string",
|
||||
displayVersion: "string",
|
||||
})
|
||||
),
|
||||
// "songs-ddr": prSchemaify(
|
||||
// PR_SongDocument({
|
||||
// displayVersion: "string",
|
||||
// })
|
||||
// ),
|
||||
"songs-sdvx": prSchemaify(
|
||||
PR_SongDocument({
|
||||
displayVersion: "string",
|
||||
})
|
||||
),
|
||||
"songs-usc": prSchemaify(PR_SongDocument({})),
|
||||
// "songs-maimai": prSchemaify(
|
||||
// PR_SongDocument({
|
||||
// titleJP: "string",
|
||||
// artistJP: "string",
|
||||
// displayVersion: "string",
|
||||
// })
|
||||
// ),
|
||||
"songs-museca": prSchemaify(
|
||||
PR_SongDocument({
|
||||
titleJP: "string",
|
||||
artistJP: "string",
|
||||
displayVersion: "string",
|
||||
})
|
||||
),
|
||||
// "songs-gitadora": prSchemaify(
|
||||
// PR_SongDocument({
|
||||
// isHot: "boolean",
|
||||
// })
|
||||
// ),
|
||||
"songs-iidx": prSchemaify(
|
||||
PR_SongDocument({
|
||||
genre: "string",
|
||||
displayVersion: "string",
|
||||
})
|
||||
),
|
||||
"songs-wacca": prSchemaify(
|
||||
PR_SongDocument({
|
||||
genre: "string",
|
||||
displayVersion: "?string",
|
||||
titleJP: "string",
|
||||
artistJP: "string",
|
||||
})
|
||||
),
|
||||
"songs-pms": prSchemaify(
|
||||
PR_SongDocument({
|
||||
genre: "?string",
|
||||
subtitle: "?string",
|
||||
subartist: "?string",
|
||||
tableString: "?string",
|
||||
})
|
||||
),
|
||||
"songs-popn": prSchemaify(
|
||||
PR_SongDocument({
|
||||
genre: "string",
|
||||
displayVersion: "?string",
|
||||
})
|
||||
),
|
||||
"songs-jubeat": prSchemaify(
|
||||
PR_SongDocument({
|
||||
displayVersion: "string",
|
||||
})
|
||||
),
|
||||
"charts-iidx": (self) => {
|
||||
const playtype = getPlaytype("iidx", self);
|
||||
|
||||
return prSchemaify(
|
||||
PR_ChartDocument("iidx", playtype, {
|
||||
notecount: p.isPositiveNonZeroInteger,
|
||||
inGameID: p.or(p.isPositiveNonZeroInteger, [p.isPositiveNonZeroInteger]),
|
||||
arcChartID: "?string",
|
||||
hashSHA256: "?string",
|
||||
"2dxtraSet": "?string",
|
||||
kaidenAverage: "?number",
|
||||
worldRecord: "?number",
|
||||
bpiCoefficient: "?number",
|
||||
})
|
||||
)(self);
|
||||
},
|
||||
"charts-bms": (self) => {
|
||||
const playtype = getPlaytype("bms", self);
|
||||
|
||||
return prSchemaify(
|
||||
PR_ChartDocument("bms", playtype, {
|
||||
notecount: p.isPositiveNonZeroInteger,
|
||||
hashSHA256: "?string",
|
||||
hashMD5: "?string",
|
||||
tableFolders: [
|
||||
{
|
||||
table: "string",
|
||||
level: "string",
|
||||
},
|
||||
],
|
||||
})
|
||||
)(self);
|
||||
},
|
||||
"charts-chunithm": prSchemaify(
|
||||
PR_ChartDocument("chunithm", "Single", {
|
||||
inGameID: p.isPositiveInteger,
|
||||
})
|
||||
),
|
||||
"charts-jubeat": prSchemaify(
|
||||
PR_ChartDocument("jubeat", "Single", {
|
||||
inGameID: p.isPositiveInteger,
|
||||
isHardMode: "boolean",
|
||||
})
|
||||
),
|
||||
// "charts-gitadora": (self) => {
|
||||
// const playtype = getPlaytype("gitadora", self);
|
||||
|
||||
// return prSchemaify(
|
||||
// PR_ChartDocument("gitadora", playtype, {
|
||||
// inGameID: p.isPositiveInteger,
|
||||
// })
|
||||
// )(self);
|
||||
// },
|
||||
// "charts-ddr": (self) => {
|
||||
// const playtype = getPlaytype("ddr", self);
|
||||
|
||||
// return prSchemaify(
|
||||
// PR_ChartDocument("ddr", playtype, {
|
||||
// inGameID: "string",
|
||||
// songHash: "string",
|
||||
// })
|
||||
// )(self);
|
||||
// },
|
||||
// "charts-maimai": prSchemaify(
|
||||
// PR_ChartDocument("maimai", "Single", {
|
||||
// maxPercent: p.gt(0),
|
||||
// inGameID: p.isPositiveInteger,
|
||||
// inGameStrID: "string",
|
||||
// })
|
||||
// ),
|
||||
"charts-museca": prSchemaify(
|
||||
PR_ChartDocument("museca", "Single", {
|
||||
inGameID: p.isPositiveInteger,
|
||||
})
|
||||
),
|
||||
"charts-sdvx": prSchemaify(
|
||||
PR_ChartDocument("sdvx", "Single", {
|
||||
inGameID: p.isPositiveInteger,
|
||||
arcChartID: "?string",
|
||||
})
|
||||
),
|
||||
"charts-usc": (self) => {
|
||||
const playtype = getPlaytype("usc", self);
|
||||
|
||||
return prSchemaify(
|
||||
PR_ChartDocument("usc", playtype, {
|
||||
hashSHA1: p.or("string", ["string"]),
|
||||
isOfficial: "boolean",
|
||||
})
|
||||
)(self);
|
||||
},
|
||||
"charts-wacca": prSchemaify(
|
||||
PR_ChartDocument("wacca", "Single", {
|
||||
isHot: "boolean",
|
||||
})
|
||||
),
|
||||
"charts-pms": (self) => {
|
||||
const playtype = getPlaytype("pms", self);
|
||||
|
||||
return prSchemaify(
|
||||
PR_ChartDocument("pms", playtype, {
|
||||
notecount: p.isPositiveNonZeroInteger,
|
||||
hashSHA256: "?string",
|
||||
hashMD5: "?string",
|
||||
tableFolders: [
|
||||
{
|
||||
table: "string",
|
||||
level: "string",
|
||||
},
|
||||
],
|
||||
})
|
||||
)(self);
|
||||
},
|
||||
"charts-popn": prSchemaify(
|
||||
PR_ChartDocument("popn", "9B", {
|
||||
hashSHA256: "?string",
|
||||
inGameID: p.isPositiveInteger,
|
||||
})
|
||||
),
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
// NOT A REAL TSCONFIG FILE
|
||||
// THIS IS USED FOR VSCODE SO IT INTEGRATES NICELY
|
||||
// IF YOU USE THIS TO BUILD, IT WILL ALSO BUILD THE TEST FILES!!
|
||||
// SO, DONT DO THAT, USE TSCONFIG.BUILD.JSON FOR THE BUILD.
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"module": "CommonJS",
|
||||
"lib": [
|
||||
"ES2019"
|
||||
],
|
||||
"declaration": true,
|
||||
"strict": false,
|
||||
"allowJs": true,
|
||||
"esModuleInterop": true,
|
||||
"sourceMap": true,
|
||||
"outDir": "./js",
|
||||
"baseUrl": "src",
|
||||
"typeRoots": [
|
||||
"@types",
|
||||
"node_modules/@types"
|
||||
],
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
]
|
||||
}
|
||||
@@ -7,7 +7,10 @@ const glob = require("glob");
|
||||
|
||||
function IterateCollections(cb) {
|
||||
for (const collection of fs.readdirSync(COLLECTIONS_DIR)) {
|
||||
const data = cb(JSON.parse(fs.readFileSync(path.join(COLLECTIONS_DIR, collection))), collection);
|
||||
const data = cb(
|
||||
JSON.parse(fs.readFileSync(path.join(COLLECTIONS_DIR, collection))),
|
||||
collection
|
||||
);
|
||||
|
||||
fs.writeFileSync(path.join(COLLECTIONS_DIR, collection), JSON.stringify(data, null, "\t"));
|
||||
}
|
||||
@@ -17,9 +20,13 @@ function IterateCollections(cb) {
|
||||
|
||||
const COLLECTIONS_DIR = path.join(__dirname, "../collections");
|
||||
|
||||
function ReadCollection(name) {
|
||||
function ReadCollection(name, throwIfNotFound = false) {
|
||||
const p = path.join(COLLECTIONS_DIR, name);
|
||||
if (!fs.existsSync(p)) {
|
||||
if (throwIfNotFound) {
|
||||
throw new Error(`No collection ${name} exists.`);
|
||||
}
|
||||
|
||||
fs.writeFileSync(p, JSON.stringify([]));
|
||||
return [];
|
||||
}
|
||||
@@ -28,7 +35,6 @@ function ReadCollection(name) {
|
||||
}
|
||||
|
||||
function MutateCollection(name, cb) {
|
||||
|
||||
const data = cb(ReadCollection(name));
|
||||
|
||||
fs.writeFileSync(path.join(COLLECTIONS_DIR, name), JSON.stringify(data, null, "\t"));
|
||||
@@ -40,11 +46,7 @@ function CreateChartID() {
|
||||
return crypto.randomBytes(20).toString("hex");
|
||||
}
|
||||
|
||||
function CreateFolderID(
|
||||
query,
|
||||
game,
|
||||
playtype
|
||||
) {
|
||||
function CreateFolderID(query, game, playtype) {
|
||||
return `F${fjsh.hash(Object.assign({ game, playtype }, query), "SHA256")}`;
|
||||
}
|
||||
|
||||
@@ -55,7 +57,7 @@ function EfficientInPlaceDeepmerge(ref, apply) {
|
||||
if (typeof apply[key] === "object" && apply[key]) {
|
||||
EfficientInPlaceDeepmerge(ref[key], apply[key]);
|
||||
} else {
|
||||
ref[key] = apply[key]
|
||||
ref[key] = apply[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,16 +73,16 @@ function AddSupportForBMSTable(header, game, playtype, tableName, tableID, table
|
||||
game,
|
||||
searchTerms: [],
|
||||
type: "charts",
|
||||
"data": {
|
||||
data: {
|
||||
"data¬tableFolders": {
|
||||
"~elemMatch": {
|
||||
"level": level.toString(),
|
||||
"table": symbol
|
||||
}
|
||||
}
|
||||
level: level.toString(),
|
||||
table: symbol,
|
||||
},
|
||||
},
|
||||
},
|
||||
inactive: false,
|
||||
}
|
||||
};
|
||||
|
||||
const folderID = CreateFolderID(f);
|
||||
|
||||
@@ -96,16 +98,16 @@ function AddSupportForBMSTable(header, game, playtype, tableName, tableID, table
|
||||
|
||||
MutateCollection("tables.json", (t) => {
|
||||
t.push({
|
||||
folders: folders.map(e => e.folderID),
|
||||
folders: folders.map((e) => e.folderID),
|
||||
game,
|
||||
playtype,
|
||||
inactive: false,
|
||||
description: tableDescription,
|
||||
title: tableName,
|
||||
tableID: tableID
|
||||
tableID: tableID,
|
||||
});
|
||||
return t;
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
@@ -115,5 +117,5 @@ module.exports = {
|
||||
CreateFolderID,
|
||||
ReadCollection,
|
||||
EfficientInPlaceDeepmerge,
|
||||
AddSupportForBMSTable
|
||||
}
|
||||
AddSupportForBMSTable,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user