mirror of
https://github.com/zkldi/Tachi.git
synced 2026-09-28 18:08:15 +03:00
Remove non-compiling scripts
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
This folder is for porting documents from the old KamaitachiDB to the newer formats.
|
||||
|
||||
The scripts here should NOT be ran unless you know *exactly* what the hell you're doing.
|
||||
|
||||
And, even then - basically only I know, so. Please be careful.
|
||||
@@ -1,79 +0,0 @@
|
||||
// oh boy
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import db from "external/mongo/db";
|
||||
import { GoalDocument } from "tachi-common";
|
||||
import CreateLogCtx from "../../src/common/logger";
|
||||
import MigrateRecords from "./migrate";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
function ConvertFn(c: any): GoalDocument | null {
|
||||
let charts: GoalDocument["charts"];
|
||||
|
||||
if (c.directChartID) {
|
||||
charts = {
|
||||
type: "single",
|
||||
data: c.directChartID,
|
||||
};
|
||||
} else if (c.directChartIDs) {
|
||||
charts = {
|
||||
type: "multi",
|
||||
data: c.directChartIDs,
|
||||
};
|
||||
} else if (c.chartQuery) {
|
||||
logger.warn(`Skipped goal ${c.title}, as it used cQuery.`);
|
||||
return null;
|
||||
} else {
|
||||
logger.warn(`Any Goal ${c.goalID}, ${c.title}. Skipping.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const partialCriteria: Partial<GoalDocument["criteria"]> = {
|
||||
mode: "single",
|
||||
};
|
||||
|
||||
if (c.scoreQuery["scoreData¬lampIndex"]) {
|
||||
partialCriteria.key = "scoreData.lampIndex";
|
||||
} else if (c.scoreQuery["scoreData¬gradeIndex"]) {
|
||||
partialCriteria.key = "scoreData.gradeIndex";
|
||||
} else if (c.scoreQuery["scoreData¬score"]) {
|
||||
partialCriteria.key = "scoreData.score";
|
||||
} else if (c.scoreQuery["scoreData¬percent"]) {
|
||||
partialCriteria.key = "scoreData.percent";
|
||||
} else {
|
||||
throw new Error(`Invalid goal ${c.goalID} ${c.title}.`);
|
||||
}
|
||||
|
||||
const v = c.scoreQuery[partialCriteria.key.replace(/\./gu, "¬")];
|
||||
|
||||
const value = v ? v["~gte"] : undefined;
|
||||
|
||||
// would break for value == 0, but a goal would never be
|
||||
// zero.
|
||||
if (!value) {
|
||||
throw new Error(`Invalid goal ${c.goalID} ${c.title}.`);
|
||||
}
|
||||
|
||||
partialCriteria.value = value;
|
||||
|
||||
// @ts-expect-error ts cant resolve this union properly
|
||||
const newGoalDoc: GoalDocument = {
|
||||
game: c.game,
|
||||
playtype: c.playtype,
|
||||
title: c.title,
|
||||
timeAdded: c.timeAdded,
|
||||
goalID: c.goalID, // maybe
|
||||
createdBy: c.createdBy,
|
||||
charts,
|
||||
criteria: partialCriteria as GoalDocument["criteria"],
|
||||
};
|
||||
|
||||
return newGoalDoc;
|
||||
}
|
||||
|
||||
(async () => {
|
||||
await MigrateRecords(db.goals, "goals", ConvertFn);
|
||||
|
||||
process.exit(0);
|
||||
})();
|
||||
@@ -1,62 +0,0 @@
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { ICollection } from "monk";
|
||||
import { oldKTDB } from "./old-db";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
export default async function MigrateRecords(
|
||||
existingCollection: ICollection,
|
||||
collectionName: string,
|
||||
HandlerFN: (c: unknown) => unknown,
|
||||
filter: Record<string, any> = {},
|
||||
force = false
|
||||
) {
|
||||
const existingRecords = await existingCollection.count({});
|
||||
logger.info(`Starting migration for ${collectionName}...`);
|
||||
|
||||
if (existingRecords > 0) {
|
||||
if (force) {
|
||||
logger.warn(
|
||||
`Forcing migration of documents - appending to ${existingRecords} existing records.`
|
||||
);
|
||||
} else {
|
||||
logger.error(`${existingRecords} documents already exist in db, terminating.`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
let i = 0;
|
||||
const bucketSize = 10_000;
|
||||
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const docs = await oldKTDB.get(collectionName).find(filter, { limit: bucketSize, skip: i });
|
||||
|
||||
logger.info(`Migrating ${i} - ${i + docs.length} documents.`);
|
||||
|
||||
if (docs.length === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const newDocs = await Promise.all(docs.map(HandlerFN));
|
||||
|
||||
i += bucketSize;
|
||||
|
||||
const notNulls = newDocs.filter((e) => e !== null);
|
||||
|
||||
logger.info(`Success: ${notNulls.length}, Failures: ${newDocs.length - notNulls.length}.`);
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await existingCollection.insert(notNulls);
|
||||
|
||||
logger.info(`Migrated ${docs.length} documents.`);
|
||||
|
||||
if (docs.length < bucketSize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
logger.info(`Done!`);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { Environment } from "lib/setup/config";
|
||||
import monk from "monk";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
logger.info(`Connecting to Old KTDB at ${Environment.mongoUrl}/kamaitachidb.`);
|
||||
|
||||
export const oldKTDB = monk(`${Environment.mongoUrl}/kamaitachidb`);
|
||||
|
||||
oldKTDB
|
||||
.then(() => {
|
||||
logger.info(`Done.`);
|
||||
})
|
||||
.catch((err) => {
|
||||
logger.crit(`Fatal in connecting to old KT DB.`, { err });
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -1,153 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import db from "external/mongo/db";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { CreateScoreID } from "lib/score-import/framework/score-importing/score-id";
|
||||
import { GetGamePTConfig, ScoreDocument, StaticConfig } from "tachi-common";
|
||||
import MigrateRecords from "../migrate";
|
||||
import { oldKTDB } from "../old-db";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
function ConditionalAssign(base: any, baseProp: string, other: any, otherProp: string) {
|
||||
if (Object.prototype.hasOwnProperty.call(other, otherProp)) {
|
||||
base[baseProp] = other[otherProp];
|
||||
}
|
||||
}
|
||||
|
||||
async function ConvertFn(c: any): Promise<ScoreDocument | null> {
|
||||
if (!StaticConfig.allSupportedGames.includes(c.game)) {
|
||||
logger.warn(`Ignored game ${c.game}`);
|
||||
return null;
|
||||
}
|
||||
const game = c.game;
|
||||
const playtype = c.scoreData.playtype;
|
||||
|
||||
const oldChartDoc = await oldKTDB.get("charts-bms").findOne({
|
||||
chartID: c.chartID,
|
||||
});
|
||||
|
||||
if (!oldChartDoc) {
|
||||
logger.warn(`Cannot find oldChartDoc for ${c.chartID}`);
|
||||
}
|
||||
|
||||
// @ts-expect-error implicit any is expected
|
||||
const chartDoc = await db.charts[game].findOne({
|
||||
"data.hashMD5": oldChartDoc.internals.hash,
|
||||
});
|
||||
|
||||
if (!chartDoc) {
|
||||
const oldSong = await oldKTDB.get("songs-bms").findOne({ id: c.songID });
|
||||
logger.warn(`Cannot find ChartDoc for ${oldSong.title} ${oldChartDoc.level} ${playtype}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const gptConfig = GetGamePTConfig(game, chartDoc.playtype);
|
||||
|
||||
if (!gptConfig) {
|
||||
logger.error(`Cannot find GPTConfig for ${game} ${chartDoc.playtype}?`);
|
||||
|
||||
throw new Error(`Screwed`);
|
||||
}
|
||||
|
||||
const base: Omit<ScoreDocument, "scoreID"> = {
|
||||
userID: c.userID,
|
||||
songID: chartDoc.songID,
|
||||
playtype: chartDoc.playtype,
|
||||
chartID: chartDoc.chartID,
|
||||
game: c.game,
|
||||
timeAdded: c.timeAdded,
|
||||
timeAchieved: Number.isNaN(c.timeAchieved) ? null : c.timeAchieved,
|
||||
comment: c.comment ?? null,
|
||||
highlight: c.highlight ?? false,
|
||||
service: c.service,
|
||||
importType: null,
|
||||
// we'll just recalc calculated data instead of trying to update
|
||||
calculatedData: {},
|
||||
isPrimary: chartDoc.isPrimary,
|
||||
scoreData: {
|
||||
esd: c.scoreData.esd ?? null,
|
||||
grade: c.scoreData.grade,
|
||||
gradeIndex: gptConfig.grades.indexOf(c.scoreData.grade),
|
||||
lamp: c.scoreData.lamp,
|
||||
lampIndex: gptConfig.lamps.indexOf(c.scoreData.lamp),
|
||||
percent: c.scoreData.percent,
|
||||
score: c.scoreData.score,
|
||||
judgements: c.scoreData.hitData,
|
||||
hitMeta: {
|
||||
fast: c.scoreData.hitMeta.fast,
|
||||
slow: c.scoreData.hitMeta.slow,
|
||||
maxCombo: c.scoreData.hitMeta.maxCombo,
|
||||
bp: c.scoreData.hitMeta.bp,
|
||||
gauge: c.scoreData.hitMeta.gauge,
|
||||
epg: c.scoreData.hitMeta.epg,
|
||||
egr: c.scoreData.hitMeta.egr,
|
||||
egd: c.scoreData.hitMeta.egd,
|
||||
ebd: c.scoreData.hitMeta.ebd,
|
||||
epr: c.scoreData.hitMeta.epr,
|
||||
lpg: c.scoreData.hitMeta.lpg,
|
||||
lgr: c.scoreData.hitMeta.lgr,
|
||||
lgd: c.scoreData.hitMeta.lgd,
|
||||
lbd: c.scoreData.hitMeta.lbd,
|
||||
lpr: c.scoreData.hitMeta.lpr,
|
||||
},
|
||||
},
|
||||
scoreMeta: {
|
||||
random: c.scoreMeta?.optionsRandom ?? null,
|
||||
inputDevice: c.scoreMeta?.inputDevice ?? null,
|
||||
},
|
||||
};
|
||||
|
||||
// @ts-expect-error shut
|
||||
if (base.scoreData.hitMeta.bp === -1 || Number.isNaN(base.scoreData.hitMeta.bp)) {
|
||||
// @ts-expect-error shut
|
||||
base.scoreData.hitMeta.bp = null;
|
||||
}
|
||||
|
||||
// @ts-expect-error shut
|
||||
if (Number(base.scoreData.hitMeta.bp) < 0) {
|
||||
// @ts-expect-error shut
|
||||
base.scoreData.hitMeta.bp = null;
|
||||
}
|
||||
|
||||
// @ts-expect-error shut
|
||||
if (base.scoreData.hitMeta.gauge === -1) {
|
||||
// @ts-expect-error shut
|
||||
base.scoreData.hitMeta.gauge = null;
|
||||
}
|
||||
|
||||
// @ts-expect-error shut
|
||||
delete base.scoreData.hitMeta.inputDevice;
|
||||
|
||||
const scoreID = CreateScoreID(base.userID, base, base.chartID);
|
||||
|
||||
const exists = await db.scores.findOne({ scoreID });
|
||||
|
||||
if (exists) {
|
||||
logger.warn(`Skipping duplicate score ${base.chartID} ${base.userID}.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const score: ScoreDocument = {
|
||||
...base,
|
||||
scoreID,
|
||||
};
|
||||
|
||||
await oldKTDB.get("score-id-lookup").insert({
|
||||
old: c.scoreID,
|
||||
new: scoreID,
|
||||
});
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
export async function MigrateBMSScores() {
|
||||
await MigrateRecords(db.scores, "scores", ConvertFn, { game: "bms" }, true);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
(async () => {
|
||||
await MigrateBMSScores();
|
||||
process.exit(0);
|
||||
})();
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import db from "external/mongo/db";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { CreateScoreID } from "lib/score-import/framework/score-importing/score-id";
|
||||
import { GetGameConfig, GetGamePTConfig, ScoreDocument } from "tachi-common";
|
||||
import MigrateRecords from "../migrate";
|
||||
import { oldKTDB } from "../old-db";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
async function ConvertFn(c: any): Promise<ScoreDocument | null> {
|
||||
const game = c.game;
|
||||
const playtype = c.scoreData.playtype;
|
||||
|
||||
const gameConfig = GetGameConfig(game);
|
||||
|
||||
if (!gameConfig.validPlaytypes.includes(playtype)) {
|
||||
logger.warn(`Ignored game pt ${game}, ${playtype}`);
|
||||
throw new Error(`Ignored game pt ${game}, ${playtype}`);
|
||||
}
|
||||
|
||||
const gptConfig = GetGamePTConfig(game, playtype);
|
||||
|
||||
if (!gptConfig) {
|
||||
logger.error(`No gptconfig for ${game} ${playtype}?`);
|
||||
throw new Error(`No gptconfig for ${game} ${playtype}?`);
|
||||
}
|
||||
|
||||
// @ts-expect-error implicit any is expected
|
||||
const chartDoc = await db.charts[game].findOne({
|
||||
songID: c.songID,
|
||||
difficulty: c.scoreData.difficulty,
|
||||
playtype,
|
||||
});
|
||||
|
||||
if (!chartDoc) {
|
||||
logger.warn(`Cannot find ChartDoc for ${c.songID} ${c.scoreData.difficulty} ${playtype} `);
|
||||
return null;
|
||||
}
|
||||
|
||||
const base: Omit<ScoreDocument<"chunithm:Single">, "scoreID"> = {
|
||||
userID: c.userID,
|
||||
songID: chartDoc.songID,
|
||||
playtype,
|
||||
chartID: chartDoc.chartID,
|
||||
game: c.game,
|
||||
timeAdded: c.timeAdded,
|
||||
timeAchieved: Number.isNaN(c.timeAchieved) ? null : c.timeAchieved,
|
||||
comment: c.comment ?? null,
|
||||
highlight: c.highlight ?? false,
|
||||
service: c.service,
|
||||
importType: null,
|
||||
// we'll just recalc calculated data instead of trying to update
|
||||
calculatedData: {},
|
||||
isPrimary: chartDoc.isPrimary,
|
||||
scoreData: {
|
||||
esd: c.scoreData.esd ?? null,
|
||||
grade: c.scoreData.grade,
|
||||
gradeIndex: gptConfig.grades.indexOf(c.scoreData.grade),
|
||||
lamp: c.scoreData.lamp,
|
||||
lampIndex: gptConfig.lamps.indexOf(c.scoreData.lamp),
|
||||
percent: c.scoreData.percent,
|
||||
score: c.scoreData.score,
|
||||
judgements: c.scoreData.hitData,
|
||||
hitMeta: c.scoreData.hitMeta,
|
||||
},
|
||||
scoreMeta: {},
|
||||
};
|
||||
|
||||
const scoreID = CreateScoreID(base.userID, base, base.chartID);
|
||||
|
||||
const exists = await db.scores.findOne({ scoreID });
|
||||
|
||||
if (exists) {
|
||||
logger.warn(`Skipping duplicate score ${base.chartID} ${base.userID}.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const score: ScoreDocument = {
|
||||
...base,
|
||||
scoreID,
|
||||
};
|
||||
|
||||
await oldKTDB.get("score-id-lookup").insert({
|
||||
old: c.scoreID,
|
||||
new: scoreID,
|
||||
});
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
export async function MigrateCHUNITHMScores() {
|
||||
await MigrateRecords(db.scores, "scores", ConvertFn, { game: "chunithm" }, true);
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import db from "external/mongo/db";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { CreateScoreID } from "lib/score-import/framework/score-importing/score-id";
|
||||
import { GetGamePTConfig, ScoreDocument, StaticConfig } from "tachi-common";
|
||||
import MigrateRecords from "../migrate";
|
||||
import { oldKTDB } from "../old-db";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
async function ConvertFn(c: any): Promise<ScoreDocument | null> {
|
||||
if (!StaticConfig.allSupportedGames.includes(c.game)) {
|
||||
logger.warn(`Ignored game ${c.game}`);
|
||||
return null;
|
||||
}
|
||||
const game = c.game;
|
||||
|
||||
// @ts-expect-error implicit any is expected
|
||||
const chartDoc = await db.charts[game].findOne({
|
||||
chartID: c.chartID,
|
||||
});
|
||||
|
||||
if (!chartDoc) {
|
||||
logger.warn(`Cannot find ChartDoc for ${c.songID} ${c.chartID} ${c.scoreData.difficulty}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const gptConfig = GetGamePTConfig(game, chartDoc.playtype);
|
||||
|
||||
if (!gptConfig) {
|
||||
logger.error(`Cannot find GPTConfig for ${game} ${chartDoc.playtype}?`);
|
||||
|
||||
throw new Error(`Screwed`);
|
||||
}
|
||||
|
||||
const base: Omit<ScoreDocument<"ddr:SP" | "ddr:DP">, "scoreID"> = {
|
||||
userID: c.userID,
|
||||
songID: chartDoc.songID,
|
||||
playtype: chartDoc.playtype,
|
||||
chartID: chartDoc.chartID,
|
||||
game: c.game,
|
||||
timeAdded: c.timeAdded,
|
||||
timeAchieved: Number.isNaN(c.timeAchieved) ? null : c.timeAchieved,
|
||||
comment: c.comment ?? null,
|
||||
highlight: c.highlight ?? false,
|
||||
service: c.service,
|
||||
importType: null,
|
||||
// we'll just recalc calculated data instead of trying to update
|
||||
calculatedData: {},
|
||||
isPrimary: chartDoc.isPrimary,
|
||||
scoreData: {
|
||||
esd: c.scoreData.esd ?? null,
|
||||
grade: c.scoreData.grade,
|
||||
gradeIndex: gptConfig.grades.indexOf(c.scoreData.grade),
|
||||
lamp: c.scoreData.lamp,
|
||||
lampIndex: gptConfig.lamps.indexOf(c.scoreData.lamp),
|
||||
percent: c.scoreData.percent,
|
||||
score: c.scoreData.score,
|
||||
judgements: c.scoreData.hitData,
|
||||
hitMeta: c.scoreData.hitMeta,
|
||||
},
|
||||
scoreMeta: {},
|
||||
};
|
||||
|
||||
const scoreID = CreateScoreID(base.userID, base, base.chartID);
|
||||
|
||||
const exists = await db.scores.findOne({ scoreID });
|
||||
|
||||
if (exists) {
|
||||
logger.warn(`Skipping duplicate score ${base.chartID} ${base.userID}.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const score: ScoreDocument = {
|
||||
...base,
|
||||
scoreID,
|
||||
};
|
||||
|
||||
try {
|
||||
await oldKTDB.get("score-id-lookup").insert({
|
||||
old: c.scoreID,
|
||||
new: scoreID,
|
||||
});
|
||||
} catch (err) {
|
||||
// whoops
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
export async function MigrateDDRScores() {
|
||||
await MigrateRecords(db.scores, "scores", ConvertFn, { game: "ddr" }, true);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
(async () => {
|
||||
await MigrateDDRScores();
|
||||
process.exit(0);
|
||||
})();
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import db from "external/mongo/db";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { CreateScoreID } from "lib/score-import/framework/score-importing/score-id";
|
||||
import { GetGameConfig, GetGamePTConfig, ScoreDocument } from "tachi-common";
|
||||
import MigrateRecords from "../migrate";
|
||||
import { oldKTDB } from "../old-db";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
async function ConvertFn(c: any): Promise<ScoreDocument | null> {
|
||||
const game = c.game;
|
||||
const playtype = c.scoreData.playtype;
|
||||
|
||||
const gameConfig = GetGameConfig(game);
|
||||
|
||||
if (!gameConfig.validPlaytypes.includes(playtype)) {
|
||||
logger.warn(`Ignored game pt ${game}, ${playtype}`);
|
||||
throw new Error(`Ignored game pt ${game}, ${playtype}`);
|
||||
}
|
||||
|
||||
const gptConfig = GetGamePTConfig(game, playtype);
|
||||
|
||||
if (!gptConfig) {
|
||||
logger.error(`No gptconfig for ${game} ${playtype}?`);
|
||||
throw new Error(`No gptconfig for ${game} ${playtype}?`);
|
||||
}
|
||||
|
||||
if (c.songID === 1819) {
|
||||
c.songID = 1121; // praludium has two songs in kt1 for some reason (tricoro 6)
|
||||
// this overrides that
|
||||
}
|
||||
|
||||
// @ts-expect-error implicit any is expected
|
||||
const chartDoc = await db.charts[game].findOne({
|
||||
songID: c.songID,
|
||||
difficulty: c.scoreData.difficulty,
|
||||
playtype,
|
||||
});
|
||||
|
||||
if (!chartDoc) {
|
||||
logger.warn(`Cannot find ChartDoc for ${c.songID} ${c.scoreData.difficulty} ${playtype} `);
|
||||
return null;
|
||||
}
|
||||
|
||||
const base: Omit<ScoreDocument<"iidx:SP" | "iidx:DP">, "scoreID"> = {
|
||||
userID: c.userID,
|
||||
songID: chartDoc.songID,
|
||||
playtype,
|
||||
chartID: chartDoc.chartID,
|
||||
game: c.game,
|
||||
timeAdded: c.timeAdded,
|
||||
timeAchieved: Number.isNaN(c.timeAchieved) ? null : c.timeAchieved,
|
||||
comment: c.comment ?? null,
|
||||
highlight: c.highlight ?? false,
|
||||
service: c.service,
|
||||
importType: null,
|
||||
// we'll just recalc calculated data instead of trying to update
|
||||
calculatedData: {},
|
||||
isPrimary: chartDoc.isPrimary,
|
||||
scoreData: {
|
||||
esd: c.scoreData.esd ?? null,
|
||||
grade: c.scoreData.grade,
|
||||
gradeIndex: gptConfig.grades.indexOf(c.scoreData.grade),
|
||||
lamp: c.scoreData.lamp,
|
||||
lampIndex: gptConfig.lamps.indexOf(c.scoreData.lamp),
|
||||
percent: c.scoreData.percent,
|
||||
score: c.scoreData.score,
|
||||
judgements: c.scoreData.hitData,
|
||||
hitMeta: c.scoreData.hitMeta,
|
||||
},
|
||||
scoreMeta: {
|
||||
random: c.scoreMeta?.optionsRandom ?? null,
|
||||
gauge: c.scoreMeta?.optionsGauge ?? null,
|
||||
assist: c.scoreMeta?.optionsAssist ?? null,
|
||||
range: c.scoreMeta?.optionsRange ?? null,
|
||||
},
|
||||
};
|
||||
|
||||
if (c.scoreMeta) {
|
||||
if (base.playtype === "DP" && !Array.isArray(base.scoreMeta.random)) {
|
||||
base.scoreMeta.random = null;
|
||||
}
|
||||
|
||||
if (c.scoreData.hitMeta.gauge < 0) {
|
||||
c.scoreData.hitMeta.gauge = null;
|
||||
}
|
||||
|
||||
if (!Array.isArray(c.scoreData.hitMeta.gaugeHistory)) {
|
||||
c.scoreData.hitMeta.gaugeHistory = null;
|
||||
}
|
||||
|
||||
// @ts-expect-error asdf
|
||||
if (base.scoreMeta.range === "") {
|
||||
base.scoreMeta.range = "NONE";
|
||||
}
|
||||
|
||||
if (c.scoreMeta.deadMeasure || c.scoreMeta.deadNote) {
|
||||
base.scoreData.hitMeta.bp = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (base.scoreData.hitMeta.bp === -1 || Number.isNaN(base.scoreData.hitMeta.bp)) {
|
||||
base.scoreData.hitMeta.bp = null;
|
||||
}
|
||||
|
||||
if ((base.scoreData.hitMeta.gauge ?? 0) > 200) {
|
||||
base.scoreData.hitMeta.gauge = null;
|
||||
}
|
||||
|
||||
if (base.scoreData.hitMeta.gaugeHistory) {
|
||||
base.scoreData.hitMeta.gaugeHistory = base.scoreData.hitMeta.gaugeHistory.map((e) =>
|
||||
(e ?? 0) > 200 ? null : e
|
||||
);
|
||||
}
|
||||
|
||||
const scoreID = CreateScoreID(base.userID, base, base.chartID);
|
||||
|
||||
const exists = await db.scores.findOne({ scoreID });
|
||||
|
||||
if (exists) {
|
||||
logger.warn(`Skipping duplicate score ${base.chartID} ${base.userID}.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const score: ScoreDocument = {
|
||||
...base,
|
||||
scoreID,
|
||||
};
|
||||
|
||||
await oldKTDB.get("score-id-lookup").insert({
|
||||
old: c.scoreID,
|
||||
new: scoreID,
|
||||
});
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
export async function MigrateIIDXScores() {
|
||||
await MigrateRecords(db.scores, "scores", ConvertFn, { game: "iidx" }, true);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
(async () => {
|
||||
await MigrateIIDXScores();
|
||||
process.exit(0);
|
||||
})();
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { MigrateBMSScores } from "./bms";
|
||||
import { MigrateCHUNITHMScores } from "./chunithm";
|
||||
import { MigrateIIDXScores } from "./iidx";
|
||||
import { MigrateMusecaScores } from "./museca";
|
||||
import { MigrateSDVXScores } from "./sdvx";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
(async () => {
|
||||
logger.info(`Migrating IIDX Scores.`);
|
||||
|
||||
await MigrateIIDXScores();
|
||||
|
||||
logger.info(`Migrating BMS Scores.`);
|
||||
await MigrateBMSScores();
|
||||
|
||||
logger.info(`Migrating MUSECA Scores.`);
|
||||
|
||||
await MigrateMusecaScores();
|
||||
|
||||
logger.info(`Migrating SDVX Scores.`);
|
||||
|
||||
await MigrateSDVXScores();
|
||||
|
||||
logger.info(`Migrating CHUNITHM Scores.`);
|
||||
|
||||
await MigrateCHUNITHMScores();
|
||||
|
||||
logger.info("Done.");
|
||||
|
||||
process.exit(0);
|
||||
})();
|
||||
@@ -1,101 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import db from "external/mongo/db";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { CreateScoreID } from "lib/score-import/framework/score-importing/score-id";
|
||||
import { GetGamePTConfig, ScoreDocument, StaticConfig } from "tachi-common";
|
||||
import MigrateRecords from "../migrate";
|
||||
import { oldKTDB } from "../old-db";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
async function ConvertFn(c: any): Promise<ScoreDocument | null> {
|
||||
if (!StaticConfig.allSupportedGames.includes(c.game)) {
|
||||
logger.warn(`Ignored game ${c.game}`);
|
||||
return null;
|
||||
}
|
||||
const game = c.game;
|
||||
|
||||
// @ts-expect-error implicit any is expected
|
||||
const chartDoc = await db.charts[game].findOne({
|
||||
chartID: c.chartID,
|
||||
});
|
||||
|
||||
if (!chartDoc) {
|
||||
logger.warn(`Cannot find ChartDoc for ${c.songID} ${c.chartID} ${c.scoreData.difficulty}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const gptConfig = GetGamePTConfig(game, chartDoc.playtype);
|
||||
|
||||
if (!gptConfig) {
|
||||
logger.error(`Cannot find GPTConfig for ${game} ${chartDoc.playtype}?`);
|
||||
|
||||
throw new Error(`Screwed`);
|
||||
}
|
||||
|
||||
const base: Omit<ScoreDocument<"museca:Single">, "scoreID"> = {
|
||||
userID: c.userID,
|
||||
songID: chartDoc.songID,
|
||||
playtype: chartDoc.playtype,
|
||||
chartID: chartDoc.chartID,
|
||||
game: c.game,
|
||||
timeAdded: c.timeAdded,
|
||||
timeAchieved: Number.isNaN(c.timeAchieved) ? null : c.timeAchieved,
|
||||
comment: c.comment ?? null,
|
||||
highlight: c.highlight ?? false,
|
||||
service: c.service,
|
||||
importType: null,
|
||||
// we'll just recalc calculated data instead of trying to update
|
||||
calculatedData: {},
|
||||
isPrimary: chartDoc.isPrimary,
|
||||
scoreData: {
|
||||
esd: c.scoreData.esd ?? null,
|
||||
grade: c.scoreData.grade,
|
||||
gradeIndex: gptConfig.grades.indexOf(c.scoreData.grade),
|
||||
lamp: c.scoreData.lamp,
|
||||
lampIndex: gptConfig.lamps.indexOf(c.scoreData.lamp),
|
||||
percent: c.scoreData.percent,
|
||||
score: c.scoreData.score,
|
||||
judgements: c.scoreData.hitData,
|
||||
hitMeta: c.scoreData.hitMeta,
|
||||
},
|
||||
scoreMeta: {},
|
||||
};
|
||||
|
||||
const scoreID = CreateScoreID(base.userID, base, base.chartID);
|
||||
|
||||
const exists = await db.scores.findOne({ scoreID });
|
||||
|
||||
if (exists) {
|
||||
logger.warn(`Skipping duplicate score ${base.chartID} ${base.userID}.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const score: ScoreDocument = {
|
||||
...base,
|
||||
scoreID,
|
||||
};
|
||||
|
||||
try {
|
||||
await oldKTDB.get("score-id-lookup").insert({
|
||||
old: c.scoreID,
|
||||
new: scoreID,
|
||||
});
|
||||
} catch (err) {
|
||||
// whoops
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
export async function MigrateMusecaScores() {
|
||||
await MigrateRecords(db.scores, "scores", ConvertFn, { game: "museca" }, true);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
(async () => {
|
||||
await MigrateMusecaScores();
|
||||
process.exit(0);
|
||||
})();
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import db from "external/mongo/db";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { CreateScoreID } from "lib/score-import/framework/score-importing/score-id";
|
||||
import { GetGameConfig, GetGamePTConfig, ScoreDocument, StaticConfig } from "tachi-common";
|
||||
import MigrateRecords from "../migrate";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
function ConditionalAssign(base: any, baseProp: string, other: any, otherProp: string) {
|
||||
if (Object.prototype.hasOwnProperty.call(other, otherProp)) {
|
||||
base[baseProp] = other[otherProp];
|
||||
}
|
||||
}
|
||||
|
||||
async function ConvertFn(c: any): Promise<ScoreDocument | null> {
|
||||
if (!StaticConfig.allSupportedGames.includes(c.game)) {
|
||||
logger.warn(`Ignored game ${c.game}`);
|
||||
return null;
|
||||
}
|
||||
const game = c.game;
|
||||
const playtype = c.scoreData.playtype;
|
||||
|
||||
if (["popn", "jubeat", "gitadora", "usc"].includes(c.game)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const gameConfig = GetGameConfig(game);
|
||||
|
||||
if (!gameConfig.validPlaytypes.includes(playtype)) {
|
||||
logger.warn(`Ignored game pt ${game}, ${playtype}`);
|
||||
throw new Error(`Ignored game pt ${game}, ${playtype}`);
|
||||
}
|
||||
|
||||
const gptConfig = GetGamePTConfig(game, playtype);
|
||||
|
||||
if (!gptConfig) {
|
||||
logger.error(`No gptconfig for ${game} ${playtype}?`);
|
||||
throw new Error(`No gptconfig for ${game} ${playtype}?`);
|
||||
}
|
||||
|
||||
if (game === "iidx" && c.songID === 1819) {
|
||||
c.songID = 1121; // praludium has two songs in kt1 for some reason (tricoro 6)
|
||||
// this overrides that
|
||||
}
|
||||
|
||||
// @ts-expect-error implicit any is expected
|
||||
const chartDoc = await db.charts[game].findOne({
|
||||
songID: c.songID,
|
||||
difficulty: c.scoreData.difficulty,
|
||||
playtype,
|
||||
});
|
||||
|
||||
if (!chartDoc) {
|
||||
logger.warn(`Cannot find ChartDoc for ${c.songID} ${c.scoreData.difficulty} ${playtype} `);
|
||||
return null;
|
||||
}
|
||||
|
||||
const base: Omit<ScoreDocument, "scoreID"> = {
|
||||
userID: c.userID,
|
||||
songID: chartDoc.songID,
|
||||
playtype,
|
||||
chartID: chartDoc.chartID,
|
||||
game: c.game,
|
||||
timeAdded: c.timeAdded,
|
||||
timeAchieved: Number.isNaN(c.timeAchieved) ? null : c.timeAchieved,
|
||||
comment: c.comment ?? null,
|
||||
highlight: c.highlight ?? false,
|
||||
service: c.service,
|
||||
importType: null,
|
||||
// we'll just recalc calculated data instead of trying to update
|
||||
calculatedData: {},
|
||||
isPrimary: chartDoc.isPrimary,
|
||||
scoreData: {
|
||||
esd: c.scoreData.esd ?? null,
|
||||
grade: c.scoreData.grade,
|
||||
gradeIndex: gptConfig.grades.indexOf(c.scoreData.grade),
|
||||
lamp: c.scoreData.lamp,
|
||||
lampIndex: gptConfig.lamps.indexOf(c.scoreData.lamp),
|
||||
percent: c.scoreData.percent,
|
||||
score: c.scoreData.score,
|
||||
judgements: c.scoreData.hitData,
|
||||
hitMeta: c.scoreData.hitMeta,
|
||||
},
|
||||
scoreMeta: {},
|
||||
};
|
||||
|
||||
if (c.scoreMeta) {
|
||||
if (base.game === "iidx") {
|
||||
ConditionalAssign(base.scoreMeta, "random", c.scoreMeta, "optionsRandom");
|
||||
ConditionalAssign(base.scoreMeta, "gauge", c.scoreMeta, "optionsGauge");
|
||||
ConditionalAssign(base.scoreMeta, "assist", c.scoreMeta, "optionsAssist");
|
||||
ConditionalAssign(base.scoreMeta, "range", c.scoreMeta, "optionsRange");
|
||||
ConditionalAssign(base.scoreMeta, "pacemaker", c.scoreMeta, "pacemaker");
|
||||
ConditionalAssign(base.scoreMeta, "pacemakerName", c.scoreMeta, "pacemakerName");
|
||||
ConditionalAssign(base.scoreMeta, "pacemakerTarget", c.scoreMeta, "pacemakerTarget");
|
||||
|
||||
// @ts-expect-error this game is iidx
|
||||
if (base.playtype === "DP" && !Array.isArray(base.scoreMeta.random)) {
|
||||
// @ts-expect-error this game is iidx
|
||||
base.scoreMeta.random = null;
|
||||
}
|
||||
|
||||
// @ts-expect-error asdf
|
||||
if (base.scoreMeta.range === "") {
|
||||
// @ts-expect-error asdf
|
||||
base.scoreMeta.range = "NONE";
|
||||
}
|
||||
} else if (base.game === "bms") {
|
||||
ConditionalAssign(base.scoreMeta, "random", c.scoreMeta, "optionsRandom");
|
||||
ConditionalAssign(base.scoreMeta, "inputDevice", c.scoreData.hitMeta, "inputDevice");
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error shut
|
||||
if (base.scoreData.hitMeta.bp === -1 || Number.isNaN(base.scoreData.hitMeta.bp)) {
|
||||
// @ts-expect-error shut
|
||||
base.scoreData.hitMeta.bp = null;
|
||||
}
|
||||
|
||||
if (base.game === "iidx") {
|
||||
// @ts-expect-error nope
|
||||
if (base.scoreData.hitMeta.gauge > 200) {
|
||||
// @ts-expect-error nope
|
||||
base.scoreData.hitMeta.gauge = null;
|
||||
}
|
||||
|
||||
// @ts-expect-error nope
|
||||
if (base.scoreData.hitMeta.gaugeHistory) {
|
||||
// @ts-expect-error nope
|
||||
base.scoreData.hitMeta.gaugeHistory = base.scoreData.hitMeta.gaugeHistory.map((e) =>
|
||||
e > 200 ? null : e
|
||||
);
|
||||
}
|
||||
} else if (base.game === "bms") {
|
||||
// @ts-expect-error shut
|
||||
if (base.scoreData.hitMeta.gauge === -1) {
|
||||
// @ts-expect-error shut
|
||||
base.scoreData.hitMeta.gauge = null;
|
||||
}
|
||||
|
||||
// @ts-expect-error shut
|
||||
delete base.scoreData.hitMeta.inputDevice;
|
||||
} else if (base.game === "sdvx" || base.game === "usc") {
|
||||
ConditionalAssign(base.scoreData.judgements, "miss", base.scoreData.judgements, "error");
|
||||
|
||||
//@ts-expect-error yea
|
||||
delete base.scoreData.judgements.error;
|
||||
} else if (base.game === "chunithm") {
|
||||
if (base.scoreData.percent === 101) {
|
||||
base.scoreData.grade = "SSS";
|
||||
}
|
||||
}
|
||||
|
||||
if (base.service === "mm") {
|
||||
base.service = "maimagic";
|
||||
}
|
||||
|
||||
const scoreID = CreateScoreID(base.userID, base, base.chartID);
|
||||
|
||||
const score: ScoreDocument = {
|
||||
...base,
|
||||
scoreID,
|
||||
};
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
(async () => {
|
||||
await MigrateRecords(db.scores, "scores", ConvertFn);
|
||||
|
||||
process.exit(0);
|
||||
})();
|
||||
@@ -1,114 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import db from "external/mongo/db";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { CreateScoreID } from "lib/score-import/framework/score-importing/score-id";
|
||||
import { GetGamePTConfig, ScoreDocument, StaticConfig } from "tachi-common";
|
||||
import MigrateRecords from "../migrate";
|
||||
import { oldKTDB } from "../old-db";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
async function ConvertFn(c: any): Promise<ScoreDocument | null> {
|
||||
if (!StaticConfig.allSupportedGames.includes(c.game)) {
|
||||
logger.warn(`Ignored game ${c.game}`);
|
||||
return null;
|
||||
}
|
||||
const game = c.game;
|
||||
|
||||
// @ts-expect-error implicit any is expected
|
||||
const chartDoc = await db.charts[game].findOne({
|
||||
chartID: c.chartID,
|
||||
});
|
||||
|
||||
if (!chartDoc) {
|
||||
logger.warn(`Cannot find ChartDoc for ${c.songID} ${c.chartID} ${c.scoreData.difficulty}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const gptConfig = GetGamePTConfig(game, chartDoc.playtype);
|
||||
|
||||
if (!gptConfig) {
|
||||
logger.error(`Cannot find GPTConfig for ${game} ${chartDoc.playtype}?`);
|
||||
|
||||
throw new Error(`Screwed`);
|
||||
}
|
||||
|
||||
const base: Omit<ScoreDocument<"sdvx:Single">, "scoreID"> = {
|
||||
userID: c.userID,
|
||||
songID: chartDoc.songID,
|
||||
playtype: chartDoc.playtype,
|
||||
chartID: chartDoc.chartID,
|
||||
game: c.game,
|
||||
timeAdded: c.timeAdded,
|
||||
timeAchieved: Number.isNaN(c.timeAchieved) ? null : c.timeAchieved,
|
||||
comment: c.comment ?? null,
|
||||
highlight: c.highlight ?? false,
|
||||
service: c.service,
|
||||
importType: null,
|
||||
// we'll just recalc calculated data instead of trying to update
|
||||
calculatedData: {},
|
||||
isPrimary: chartDoc.isPrimary,
|
||||
scoreData: {
|
||||
esd: c.scoreData.esd ?? null,
|
||||
grade: c.scoreData.grade,
|
||||
gradeIndex: gptConfig.grades.indexOf(c.scoreData.grade),
|
||||
lamp: c.scoreData.lamp,
|
||||
lampIndex: gptConfig.lamps.indexOf(c.scoreData.lamp),
|
||||
percent: c.scoreData.percent,
|
||||
score: c.scoreData.score,
|
||||
judgements: c.scoreData.hitData,
|
||||
hitMeta: {
|
||||
fast: c.scoreData.hitMeta.fast,
|
||||
slow: c.scoreData.hitMeta.slow,
|
||||
maxCombo: c.scoreData.hitMeta.maxCombo,
|
||||
gauge: c.scoreData.hitMeta.gauge,
|
||||
},
|
||||
},
|
||||
scoreMeta: {
|
||||
inSkillAnalyser: null,
|
||||
},
|
||||
};
|
||||
|
||||
if (c.scoreData.hitData.error !== undefined) {
|
||||
base.scoreData.judgements.miss = c.scoreData.hitData.error;
|
||||
// @ts-expect-error yeah we know
|
||||
delete base.scoreData.judgements.error;
|
||||
}
|
||||
|
||||
const scoreID = CreateScoreID(base.userID, base, base.chartID);
|
||||
|
||||
const exists = await db.scores.findOne({ scoreID });
|
||||
|
||||
if (exists) {
|
||||
logger.warn(`Skipping duplicate score ${base.chartID} ${base.userID}.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const score: ScoreDocument = {
|
||||
...base,
|
||||
scoreID,
|
||||
};
|
||||
|
||||
try {
|
||||
await oldKTDB.get("score-id-lookup").insert({
|
||||
old: c.scoreID,
|
||||
new: scoreID,
|
||||
});
|
||||
} catch (err) {
|
||||
// lol
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
export async function MigrateSDVXScores() {
|
||||
await MigrateRecords(db.scores, "scores", ConvertFn, { game: "sdvx" }, true);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
(async () => {
|
||||
await MigrateSDVXScores();
|
||||
process.exit(0);
|
||||
})();
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import db from "external/mongo/db";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { CreateSessionID } from "lib/score-import/framework/sessions/sessions";
|
||||
import { GetGameConfig, integer, SessionDocument, SessionScoreInfo } from "tachi-common";
|
||||
import { allSupportedGames } from "tachi-common/js/config/static-config";
|
||||
import MigrateRecords from "./migrate";
|
||||
import { oldKTDB } from "./old-db";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
interface LegacySessionScoreFormat {
|
||||
pbInfo: {
|
||||
isGeneralPB: boolean;
|
||||
isGradePB: boolean;
|
||||
isLampPB: boolean;
|
||||
isNewScore: boolean;
|
||||
lampDelta: integer;
|
||||
percentDelta: number;
|
||||
gradeDelta: integer;
|
||||
scoreDelta: number;
|
||||
};
|
||||
scoreID: string;
|
||||
}
|
||||
|
||||
async function ConvertScoreToScoreInfo(
|
||||
score: LegacySessionScoreFormat
|
||||
): Promise<SessionScoreInfo | null> {
|
||||
const scoreIDs = await oldKTDB.get("score-id-lookup").findOne({
|
||||
old: score.scoreID,
|
||||
});
|
||||
|
||||
if (!scoreIDs) {
|
||||
logger.verbose(`No score for ${score.scoreID}? Skipping.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
logger.verbose(`Found score for ${score.scoreID}.`);
|
||||
|
||||
if (score.pbInfo.isNewScore) {
|
||||
return {
|
||||
isNewScore: true,
|
||||
scoreID: scoreIDs.new,
|
||||
};
|
||||
}
|
||||
|
||||
if (score.pbInfo.scoreDelta === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
scoreID: scoreIDs.new,
|
||||
isNewScore: false,
|
||||
gradeDelta: score.pbInfo.gradeDelta,
|
||||
lampDelta: score.pbInfo.lampDelta,
|
||||
percentDelta: score.pbInfo.percentDelta,
|
||||
scoreDelta: score.pbInfo.scoreDelta,
|
||||
};
|
||||
}
|
||||
|
||||
async function ConvertFn(c: any): Promise<SessionDocument | null> {
|
||||
if (!allSupportedGames.includes(c.game)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const gameConfig = GetGameConfig(c.game);
|
||||
|
||||
if (!gameConfig.validPlaytypes.includes(c.playtype)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const scores = [];
|
||||
|
||||
for (const sc of c.scores) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const conv = await ConvertScoreToScoreInfo(sc);
|
||||
|
||||
if (conv === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
scores.push(conv);
|
||||
}
|
||||
|
||||
const sessionDocument: SessionDocument = {
|
||||
name: c.name,
|
||||
desc: c.desc,
|
||||
timeStarted: c.timeStarted,
|
||||
timeEnded: c.timeEnded,
|
||||
timeInserted: c.timestamp,
|
||||
game: c.game,
|
||||
playtype: c.playtype,
|
||||
highlight: !!c.highlight,
|
||||
sessionID: CreateSessionID(),
|
||||
views: 0,
|
||||
userID: c.userID,
|
||||
calculatedData: {},
|
||||
scoreInfo: scores,
|
||||
importType: null,
|
||||
};
|
||||
|
||||
return sessionDocument;
|
||||
}
|
||||
|
||||
(async () => {
|
||||
await MigrateRecords(db.sessions, "sessions", ConvertFn, {}, true);
|
||||
|
||||
process.exit(0);
|
||||
})();
|
||||
@@ -1,26 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import db from "external/mongo/db";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { UserGoalDocument } from "tachi-common";
|
||||
import MigrateRecords from "./migrate";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
async function ConvertFn(c: any): Promise<UserGoalDocument | null> {
|
||||
// const newUG: UserGoalDocument = {};
|
||||
|
||||
const relatedGoal = await db.goals.findOne({ goalID: c.goalID });
|
||||
|
||||
if (!relatedGoal) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
(async () => {
|
||||
await MigrateRecords(db["user-goals"], "user-goals", ConvertFn);
|
||||
|
||||
process.exit(0);
|
||||
})();
|
||||
@@ -1,19 +0,0 @@
|
||||
import db from "external/mongo/db";
|
||||
import { PrivateUserInfoDocument } from "tachi-common";
|
||||
import MigrateRecords from "./migrate";
|
||||
|
||||
function ConvertFn(c: any): PrivateUserInfoDocument {
|
||||
const privateUserInfoDoc: PrivateUserInfoDocument = {
|
||||
userID: c.id,
|
||||
password: c.password,
|
||||
email: c.email,
|
||||
};
|
||||
|
||||
return privateUserInfoDoc;
|
||||
}
|
||||
|
||||
(async () => {
|
||||
await MigrateRecords(db["user-private-information"], "users", ConvertFn);
|
||||
|
||||
process.exit(0);
|
||||
})();
|
||||
@@ -1,15 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
import db from "external/mongo/db";
|
||||
import { DEFAULT_USER_SETTINGS } from "server/router/api/v1/auth/auth";
|
||||
import MigrateRecords from "./migrate";
|
||||
|
||||
function ConvertFn(c: any) {
|
||||
return { userID: c.id, preferences: DEFAULT_USER_SETTINGS };
|
||||
}
|
||||
|
||||
(async () => {
|
||||
await MigrateRecords(db["user-settings"], "users", ConvertFn);
|
||||
|
||||
process.exit(0);
|
||||
})();
|
||||
@@ -1,36 +0,0 @@
|
||||
import db from "external/mongo/db";
|
||||
import { PublicUserDocument, UserAuthLevels } from "tachi-common";
|
||||
import MigrateRecords from "./migrate";
|
||||
|
||||
function ConvertFn(c: any): PublicUserDocument {
|
||||
const newUserDoc: PublicUserDocument = {
|
||||
username: c.username,
|
||||
usernameLowercase: c.username.toLowerCase(),
|
||||
about: c.about,
|
||||
clan: c.clan,
|
||||
customBannerLocation: null,
|
||||
customPfpLocation: null,
|
||||
id: c.id,
|
||||
lastSeen: c.lastSeen,
|
||||
socialMedia: {
|
||||
discord: c.socialmedia.discord || null,
|
||||
twitter: c.socialmedia.twitter || null,
|
||||
youtube: c.socialmedia.youtube || null,
|
||||
twitch: c.socialmedia.twitch || null,
|
||||
github: c.socialmedia.github || null,
|
||||
steam: c.socialmedia.steam || null,
|
||||
},
|
||||
joinDate: 0,
|
||||
authLevel: UserAuthLevels.USER,
|
||||
status: null,
|
||||
badges: ["beta"],
|
||||
};
|
||||
|
||||
return newUserDoc;
|
||||
}
|
||||
|
||||
(async () => {
|
||||
await MigrateRecords(db.users, "users", ConvertFn);
|
||||
|
||||
process.exit(0);
|
||||
})();
|
||||
@@ -1,213 +0,0 @@
|
||||
/* eslint-disable no-await-in-loop */
|
||||
import { Command } from "commander";
|
||||
import db from "external/mongo/db";
|
||||
import fs from "fs";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { ServerConfig } from "lib/setup/config";
|
||||
import path from "path";
|
||||
import fetch from "utils/fetch";
|
||||
import { FindChartWithPTDFVersion, FindSDVXChartOnDFVersion } from "utils/queries/charts";
|
||||
import { FindSongOnTitle } from "utils/queries/songs";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program.option("-u, --url <URL>", "The base URL to sync from.");
|
||||
program.option("-b, --bearer <token>", "The authorization bearer token to use.");
|
||||
program.option("-g, --game <game>", "Should be exactly iidx or sdvx.");
|
||||
program.option("-c, --cache", "Use a local cached JSON file, instead of requesting from the api.");
|
||||
|
||||
program.parse(process.argv);
|
||||
const options = program.opts();
|
||||
|
||||
if (!options.game) {
|
||||
throw new Error(`Expected -g or --game parameter.`);
|
||||
}
|
||||
|
||||
if (!["iidx", "sdvx"].includes(options.game)) {
|
||||
throw new Error(`Expected provided game to be either iidx or sdvx.`);
|
||||
}
|
||||
|
||||
async function GetSongs() {
|
||||
const allSongs = [];
|
||||
|
||||
let url =
|
||||
options.game === "iidx"
|
||||
? `${ServerConfig.ARC_API_URL}/api/v1/iidx/28/music/`
|
||||
: `${ServerConfig.ARC_API_URL}/api/v1/sdvx/5/music/`;
|
||||
|
||||
let moreData = true;
|
||||
while (moreData) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const songs = await fetch(url, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${options.bearer}`,
|
||||
},
|
||||
}).then((r) => r.json());
|
||||
|
||||
if (songs._links._next) {
|
||||
url = songs._links._next;
|
||||
} else {
|
||||
moreData = false;
|
||||
}
|
||||
|
||||
allSongs.push(...songs._items);
|
||||
}
|
||||
|
||||
return allSongs;
|
||||
}
|
||||
|
||||
async function GetCharts() {
|
||||
const songs = await GetSongs();
|
||||
|
||||
const allCharts: any[] = [];
|
||||
const failed: any[] = [];
|
||||
|
||||
async function DoStuff(song: any) {
|
||||
const url =
|
||||
options.game === "iidx"
|
||||
? `${ServerConfig.ARC_API_URL}/api/v1/iidx/28/charts/?music_id=${song._id}&omnimix=true`
|
||||
: `${ServerConfig.ARC_API_URL}/api/v1/sdvx/5/charts/?music_id=${song._id}`;
|
||||
|
||||
try {
|
||||
logger.info(`Starting Request ${url}.`);
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const charts = await fetch(url, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${options.bearer}`,
|
||||
},
|
||||
}).then((r) => r.json());
|
||||
|
||||
logger.info(`Parsed: ${charts._related.music[0].title}`);
|
||||
|
||||
allCharts.push(charts);
|
||||
} catch (err) {
|
||||
logger.error(err.message, { song, err });
|
||||
failed.push(err);
|
||||
}
|
||||
}
|
||||
|
||||
for (const song of songs) {
|
||||
await DoStuff(song);
|
||||
}
|
||||
|
||||
// fast, but ARCs server cant keep up.
|
||||
// const promises = songs.map((s: any) => DoStuff(s));
|
||||
// await Promise.all(promises);
|
||||
|
||||
logger.info(failed);
|
||||
|
||||
logger.info("Retrieved charts.");
|
||||
return allCharts;
|
||||
}
|
||||
|
||||
const cacheLoc = path.join(__dirname, "cache.json");
|
||||
|
||||
async function MergeIDs() {
|
||||
let charts;
|
||||
|
||||
if (options.cache) {
|
||||
logger.info(`--cache provided, reading cache.`);
|
||||
try {
|
||||
charts = JSON.parse(fs.readFileSync(cacheLoc, "utf-8"));
|
||||
} catch (err) {
|
||||
throw new Error(`No cache, cannot use --cache!`);
|
||||
}
|
||||
} else {
|
||||
logger.info(`Reading from arc.`);
|
||||
|
||||
charts = await GetCharts();
|
||||
}
|
||||
|
||||
fs.writeFileSync(cacheLoc, JSON.stringify(charts));
|
||||
|
||||
for (const chartData of charts) {
|
||||
const songTitle = chartData._related.music[0].title;
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const song = await FindSongOnTitle(options.game, songTitle);
|
||||
|
||||
if (!song) {
|
||||
logger.error(`Could not resolve song ${songTitle}?`);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const chart of chartData._items) {
|
||||
if (chart.rating === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const playtype: "SP" | "DP" | "Single" =
|
||||
options.game === "iidx" ? (chart.play_style === "DOUBLE" ? "DP" : "SP") : "Single";
|
||||
|
||||
let difficulty = chart.difficulty === "BLACK" ? "LEGGENDARIA" : chart.difficulty;
|
||||
const version = options.game === "iidx" ? "28-omni" : "vivid";
|
||||
|
||||
// yeah this fails for wacky playtype mismatches -- i don't care.
|
||||
if (
|
||||
["ミッドナイト堕天使", "Y&Co. is dead or alive", "State Of The Art"].includes(
|
||||
songTitle
|
||||
) &&
|
||||
difficulty === "LEGGENDARIA"
|
||||
) {
|
||||
difficulty = "ANOTHER";
|
||||
}
|
||||
|
||||
let tachiChart;
|
||||
if (options.game === "sdvx") {
|
||||
tachiChart = await FindSDVXChartOnDFVersion(
|
||||
song.id,
|
||||
difficulty === "INF" ? "ANY_INF" : difficulty,
|
||||
version as "vivid"
|
||||
);
|
||||
} else {
|
||||
tachiChart = await FindChartWithPTDFVersion(
|
||||
options.game,
|
||||
song.id,
|
||||
playtype,
|
||||
difficulty,
|
||||
version
|
||||
);
|
||||
}
|
||||
|
||||
if (!tachiChart) {
|
||||
logger.error(
|
||||
`Could not find chart ${songTitle} ${playtype} ${difficulty} ${version} (SongID ${song.id}).`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await db.charts[options.game as "sdvx" | "iidx"].update(
|
||||
{
|
||||
chartID: tachiChart.chartID,
|
||||
},
|
||||
{
|
||||
$set: {
|
||||
"data.arcChartID": chart._id,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await db.charts[options.game as "sdvx" | "iidx"].update(
|
||||
{
|
||||
"data.arcChartID": { $exists: false },
|
||||
},
|
||||
{ $set: { "data.arcChartID": null } },
|
||||
{
|
||||
multi: true,
|
||||
}
|
||||
);
|
||||
|
||||
logger.info("done.");
|
||||
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
MergeIDs();
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
/* eslint-disable no-await-in-loop */
|
||||
import db from "external/mongo/db";
|
||||
import fs from "fs";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import path from "path";
|
||||
import { FindSongOnTitleInsensitive } from "utils/queries/songs";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
const comicallyLargeJSONData = JSON.parse(
|
||||
fs.readFileSync(path.join(__dirname, "./versions.json"), "utf-8")
|
||||
);
|
||||
|
||||
const DIFF_MAP = {
|
||||
A: "ANOTHER",
|
||||
H: "HYPER",
|
||||
N: "NORMAL",
|
||||
B: "BEGINNER",
|
||||
X: "LEGGENDARIA",
|
||||
} as any;
|
||||
|
||||
function ConvertVersion(c: string): any {
|
||||
if (c.startsWith("AC")) {
|
||||
return c.split("AC")[1];
|
||||
} else if (c.startsWith("OM")) {
|
||||
return `${c.split("OM")[1]}-omni`;
|
||||
} else if (c.startsWith("CS")) {
|
||||
return `${c.split("CS")[1]}-cs`;
|
||||
} else if (c === "INF") {
|
||||
return "inf";
|
||||
} else if (c === "BMUS") {
|
||||
return "bmus";
|
||||
} else {
|
||||
logger.error(`Invalid Chart Version ${c}.`);
|
||||
throw new Error("Invalid Chart Version");
|
||||
}
|
||||
}
|
||||
|
||||
(async () => {
|
||||
for (const data of comicallyLargeJSONData) {
|
||||
const song = await FindSongOnTitleInsensitive("iidx", data["MUSIC NAME"]);
|
||||
|
||||
if (!song) {
|
||||
logger.error(`Can't find song with title ${data["MUSIC NAME"]}.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const playtype = data.STYLE === "S" ? "SP" : "DP";
|
||||
|
||||
const difficulty = DIFF_MAP[data.DIFF];
|
||||
|
||||
const relevantVersions = [
|
||||
"OM27",
|
||||
"OM26",
|
||||
"AC27",
|
||||
"AC26",
|
||||
"AC25",
|
||||
"AC24",
|
||||
"AC23",
|
||||
"AC22",
|
||||
"AC21",
|
||||
"AC20",
|
||||
"INF",
|
||||
"CS16",
|
||||
"CS15",
|
||||
"CS14",
|
||||
"CS13",
|
||||
"CS12",
|
||||
"CS11",
|
||||
"CS10",
|
||||
"CS9",
|
||||
"CS8",
|
||||
"CS7",
|
||||
"BMUS",
|
||||
"CS6",
|
||||
"CS5",
|
||||
"CS4",
|
||||
"CS3",
|
||||
]
|
||||
.filter((e) => data[e] === "1")
|
||||
.map(ConvertVersion);
|
||||
|
||||
if (!relevantVersions.includes("27-omni") && !relevantVersions.includes("inf")) {
|
||||
if (relevantVersions.includes("26-omni")) {
|
||||
logger.info(
|
||||
`Song ${song.title} (${playtype} ${difficulty}) was a very recent removal. Consider deprimarifying it. (had ${relevantVersions})`,
|
||||
{ keys: Object.keys(data).filter((e) => data[e] === "1") }
|
||||
);
|
||||
} else {
|
||||
logger.verbose(
|
||||
`Song ${song.title} (${playtype} ${difficulty}) has no relevant versions. (had ${relevantVersions})`,
|
||||
{ keys: Object.keys(data).filter((e) => data[e] === "1") }
|
||||
);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
const chart = await db.charts.iidx.findOne(
|
||||
{ songID: song.id, difficulty, playtype },
|
||||
{ projectID: true }
|
||||
);
|
||||
|
||||
if (!chart) {
|
||||
logger.error(`Can't find chart ${song.title} (${playtype} ${difficulty})`);
|
||||
continue;
|
||||
}
|
||||
|
||||
relevantVersions.push(...chart.versions.filter((e) => !relevantVersions.includes(e)));
|
||||
|
||||
await db.charts.iidx.update({ _id: chart._id }, { $set: { versions: relevantVersions } });
|
||||
}
|
||||
|
||||
logger.info("done");
|
||||
|
||||
process.exit(0);
|
||||
})();
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,172 +0,0 @@
|
||||
/* eslint-disable no-await-in-loop */
|
||||
import db from "external/mongo/db";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import {
|
||||
FormatGame,
|
||||
GetGameConfig,
|
||||
GetGamePTConfig,
|
||||
IDStrings,
|
||||
integer,
|
||||
StaticConfig,
|
||||
} from "tachi-common";
|
||||
import { CreateFolderID } from "utils/folder";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
function StrRange(min: integer, max: integer) {
|
||||
const arr = [];
|
||||
for (let i = min; i <= max; i++) {
|
||||
arr.push(i.toString());
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
// These are the games that have simple, discrete folders.
|
||||
const STATIC_LEVELS: Partial<Record<IDStrings, string[]>> = {
|
||||
"iidx:SP": StrRange(1, 12),
|
||||
"iidx:DP": StrRange(1, 12),
|
||||
"bms:7K": [],
|
||||
"bms:14K": [],
|
||||
"chunithm:Single": [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"7+",
|
||||
"8",
|
||||
"8+",
|
||||
"9",
|
||||
"9+",
|
||||
"10",
|
||||
"10+",
|
||||
"11",
|
||||
"11+",
|
||||
"12",
|
||||
"12+",
|
||||
"13",
|
||||
"13+",
|
||||
"14",
|
||||
"14+",
|
||||
],
|
||||
"maimai:Single": [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"7+",
|
||||
"8",
|
||||
"8+",
|
||||
"9",
|
||||
"9+",
|
||||
"10",
|
||||
"10+",
|
||||
"11",
|
||||
"11+",
|
||||
"12",
|
||||
"12+",
|
||||
"13",
|
||||
"13+",
|
||||
"14",
|
||||
],
|
||||
"museca:Single": StrRange(1, 15),
|
||||
"sdvx:Single": StrRange(1, 20),
|
||||
"ddr:SP": StrRange(1, 20),
|
||||
"ddr:DP": StrRange(1, 20),
|
||||
};
|
||||
|
||||
async function InsertStaticLevelVersionFolders() {
|
||||
// Little known fact: I invented the cyclomatic complexity warning
|
||||
for (const { game, playtype } of GPTYielder()) {
|
||||
const gameConfig = GetGameConfig(game);
|
||||
const gptConfig = GetGamePTConfig(game, playtype);
|
||||
|
||||
for (const version of gptConfig.supportedVersions) {
|
||||
// @ts-expect-error dont worry
|
||||
const staticLevels = STATIC_LEVELS[`${game}:${playtype}`];
|
||||
|
||||
if (!staticLevels) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let inactive = false;
|
||||
|
||||
if (
|
||||
!(
|
||||
gptConfig.currentGameOmniVersion === version ||
|
||||
gptConfig.currentLatestVersion === version ||
|
||||
gptConfig.currentLocalVersion === version
|
||||
)
|
||||
) {
|
||||
inactive = true;
|
||||
}
|
||||
|
||||
await db.tables.insert({
|
||||
tableID: `${game}-${playtype}-${version}-levels`,
|
||||
description: `Levels for ${FormatGame(game, playtype)} in version ${version}.`,
|
||||
title: `${FormatGame(game, playtype)} (${version})`,
|
||||
folders: [],
|
||||
game,
|
||||
playtype,
|
||||
inactive,
|
||||
});
|
||||
|
||||
for (const level of staticLevels) {
|
||||
const query = {
|
||||
level,
|
||||
versions: version,
|
||||
};
|
||||
|
||||
const folderID = CreateFolderID(query, game, playtype);
|
||||
|
||||
await db.folders.insert({
|
||||
folderID,
|
||||
game,
|
||||
playtype,
|
||||
title: `Level ${level} (${version})`,
|
||||
type: "charts",
|
||||
data: query,
|
||||
searchTerms: [],
|
||||
inactive,
|
||||
});
|
||||
|
||||
await db.tables.update(
|
||||
{
|
||||
tableID: `${game}-${playtype}-${version}-levels`,
|
||||
},
|
||||
{
|
||||
$push: {
|
||||
folders: folderID,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
logger.info(`Inserted ${gameConfig.name} Level ${level} (${version})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info(`Done.`);
|
||||
}
|
||||
|
||||
function* GPTYielder() {
|
||||
for (const game of StaticConfig.allSupportedGames) {
|
||||
const gameConfig = GetGameConfig(game);
|
||||
for (const playtype of gameConfig.validPlaytypes) {
|
||||
yield { game, playtype };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Some games don't use "fixed" levels per se, and as such breaking
|
||||
// the folders up are quite hard. This is for *those* games.
|
||||
async function InsertCustomStuff() {}
|
||||
|
||||
(async () => {
|
||||
await InsertStaticLevelVersionFolders();
|
||||
})();
|
||||
@@ -26,6 +26,6 @@ db.invites
|
||||
consumedAt: null,
|
||||
})
|
||||
.then(() => {
|
||||
console.log(`Created invite ${options.code}.`);
|
||||
logger.info(`Created invite ${options.code}.`);
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import db from "external/mongo/db";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
(async () => {
|
||||
logger.info(`Setting tableFolders.`);
|
||||
const r = await db.charts.bms.update(
|
||||
{},
|
||||
{ $set: { "data.tableFolders": [] } },
|
||||
{ multi: true }
|
||||
);
|
||||
logger.info(`Done!`, { r });
|
||||
|
||||
process.exit(0);
|
||||
})();
|
||||
@@ -1,20 +0,0 @@
|
||||
import db from "external/mongo/db";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { TachiConfig } from "lib/setup/config";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
if (require.main === module) {
|
||||
(async () => {
|
||||
for (const game of TachiConfig.GAMES) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const res = await db.charts[game].update(
|
||||
{ tierlistInfo: { $exists: false } },
|
||||
{ $set: { tierlistInfo: {} } },
|
||||
{ multi: true }
|
||||
);
|
||||
|
||||
logger.info(`Added tierlistInfo to ${game}'s charts.`, { res });
|
||||
}
|
||||
})();
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/* eslint-disable no-await-in-loop */
|
||||
import db from "external/mongo/db";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { GetGamePTConfig } from "tachi-common";
|
||||
import { GenericGetGradeAndPercent } from "lib/score-import/framework/common/score-utils";
|
||||
import UpdateScore from "lib/score-mutation/update-score";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
if (require.main === module) {
|
||||
(async () => {
|
||||
const gptConfig = GetGamePTConfig("iidx", "SP");
|
||||
|
||||
for (const [key, grade] of gptConfig.grades.entries()) {
|
||||
const badScores = await db.scores.find({
|
||||
game: "iidx",
|
||||
"scoreData.grade": grade,
|
||||
"scoreData.percent": { $lt: gptConfig.gradeBoundaries[key] },
|
||||
});
|
||||
|
||||
logger.info(`${grade} (${gptConfig.gradeBoundaries[key]}) ${badScores.length}`);
|
||||
|
||||
for (const badScore of badScores) {
|
||||
const chart = await db.charts.iidx.findOne({ chartID: badScore.chartID });
|
||||
|
||||
if (!chart) {
|
||||
logger.severe(
|
||||
`Couldn't find chart for ${badScore.chartID}, yet scores exist on it?`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
const newScore = JSON.parse(JSON.stringify(badScore));
|
||||
|
||||
const { grade } = GenericGetGradeAndPercent(
|
||||
"iidx",
|
||||
badScore.scoreData.score,
|
||||
chart
|
||||
);
|
||||
|
||||
newScore.scoreData.grade = grade;
|
||||
newScore.scoreData.gradeIndex = gptConfig.grades.indexOf(grade);
|
||||
|
||||
await UpdateScore(badScore, newScore);
|
||||
}
|
||||
}
|
||||
|
||||
process.exit(0);
|
||||
})();
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/* eslint-disable no-await-in-loop */
|
||||
import db from "external/mongo/db";
|
||||
import { rootLogger } from "lib/logger/logger";
|
||||
import { ChartDocument, Difficulties } from "tachi-common";
|
||||
import { FindIIDXChartOnInGameID } from "utils/queries/charts";
|
||||
|
||||
async function ConvertChart(chart: ChartDocument<"iidx:SP" | "iidx:DP">) {
|
||||
// We need to get the related official song. The best way to do this is
|
||||
// probably with song IDs.
|
||||
|
||||
const originalChart = await FindIIDXChartOnInGameID(
|
||||
chart.data.inGameID,
|
||||
chart.playtype,
|
||||
chart.difficulty
|
||||
);
|
||||
|
||||
if (!originalChart) {
|
||||
rootLogger.error(`Can't find original chart.`, { chart });
|
||||
throw new Error(`Can't find original chart.`);
|
||||
}
|
||||
|
||||
return {
|
||||
difficulty: `${chart.data["2dxtraSet"]!} ${chart.difficulty}` as Difficulties[
|
||||
| "iidx:SP"
|
||||
| "iidx:DP"],
|
||||
songID: originalChart!.songID,
|
||||
};
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
(async () => {
|
||||
const modCharts = (await db.charts.iidx.find({
|
||||
"data.2dxtraSet": { $ne: null },
|
||||
difficulty: { $in: ["BEGINNER", "NORMAL", "HYPER", "ANOTHER", "LEGGENDARIA"] },
|
||||
})) as ChartDocument<"iidx:SP" | "iidx:DP">[];
|
||||
|
||||
rootLogger.info(`Modifying ${modCharts.length} charts.`);
|
||||
|
||||
for (const chart of modCharts) {
|
||||
const setDoc = await ConvertChart(chart);
|
||||
|
||||
await db.charts.iidx.update(
|
||||
{
|
||||
chartID: chart.chartID,
|
||||
},
|
||||
{ $set: setDoc }
|
||||
);
|
||||
|
||||
// We're also going to have to port over old scores.
|
||||
|
||||
await db.scores.update(
|
||||
{
|
||||
chartID: chart.chartID,
|
||||
},
|
||||
{
|
||||
$set: {
|
||||
songID: setDoc.songID,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
rootLogger.info(`Removing ${modCharts.length} songs.`);
|
||||
|
||||
await db.songs.iidx.remove({
|
||||
id: { $in: modCharts.map((e) => e.songID) },
|
||||
});
|
||||
|
||||
rootLogger.info(`Done.`);
|
||||
})();
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import { Command } from "commander";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
const program = new Command();
|
||||
program.option("-d, --dir <dir>");
|
||||
|
||||
program.parse(process.argv);
|
||||
const options = program.opts();
|
||||
|
||||
if (!options.dir) {
|
||||
throw new Error(`No dir provided, yet one is necessary.`);
|
||||
}
|
||||
|
||||
// @warn THIS SCRIPT IS OUTDATED!
|
||||
// Tachi now uses /users/${userID}/banner instead of
|
||||
// /users/banner/${userID}
|
||||
|
||||
fs.mkdirSync("users/banner", { recursive: true });
|
||||
fs.mkdirSync("users/pfp", { recursive: true });
|
||||
|
||||
for (const file of fs.readdirSync(options.dir)) {
|
||||
const dfile = path.join(options.dir, file);
|
||||
if (file.endsWith("-banner.png")) {
|
||||
fs.copyFileSync(dfile, `users/banner/${file.split("-banner.png")[0]}`);
|
||||
} else {
|
||||
fs.copyFileSync(dfile, `users/pfp/${file.split("-pfp.png")[0]}`);
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
import db from "external/mongo/db";
|
||||
|
||||
(async () => {
|
||||
const folders = await db.folders.find({}, { sort: { tableIndex: 1 } });
|
||||
|
||||
for (const folder of folders) {
|
||||
const { game, playtype } = folder;
|
||||
|
||||
const tableID = ((folder as any).table as string)
|
||||
.toLowerCase()
|
||||
.replace(/ /gu, "_")
|
||||
.replace(/\(/gu, "")
|
||||
.replace(/\)/gu, "");
|
||||
|
||||
console.log(game, playtype, tableID, folder.title);
|
||||
|
||||
const existingTable = await db.tables.findOne({ game, playtype, tableID });
|
||||
|
||||
if (!existingTable) {
|
||||
await db.tables.insert({
|
||||
tableID,
|
||||
game,
|
||||
playtype,
|
||||
description: "todo",
|
||||
folders: [folder.folderID],
|
||||
// @ts-expect-error yea
|
||||
title: folder.table,
|
||||
});
|
||||
} else {
|
||||
await db.tables.update(
|
||||
{
|
||||
game,
|
||||
playtype,
|
||||
tableID,
|
||||
},
|
||||
{
|
||||
$push: {
|
||||
folders: folder.folderID,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
})();
|
||||
@@ -1,76 +0,0 @@
|
||||
/* eslint-disable no-await-in-loop */
|
||||
import db from "external/mongo/db";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { CreatePBDoc, UpdateChartRanking } from "lib/score-import/framework/pb/create-pb-doc";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
(async () => {
|
||||
// in an alternate timeline this would be 2020 10 02,
|
||||
// but i have to account for *those* idiots.
|
||||
// who now mean i'm shredding other people scores.
|
||||
// - not zkldi
|
||||
const hvSt = new Date(2020, 9, 1);
|
||||
|
||||
const charts = await db.charts.iidx.find({
|
||||
songID: 167, // 761 -> rising in the sun; 167 -> sometime.
|
||||
isPrimary: false,
|
||||
});
|
||||
|
||||
const chartIDs = charts.map((e) => e.chartID);
|
||||
|
||||
const affectedUsers = await db.scores.find({
|
||||
chartID: { $in: chartIDs },
|
||||
timeAchieved: {
|
||||
$gt: hvSt.getTime(),
|
||||
},
|
||||
});
|
||||
|
||||
const userIDs = affectedUsers.map((e) => e.userID);
|
||||
|
||||
const r = await db.scores.remove({
|
||||
chartID: { $in: chartIDs },
|
||||
timeAchieved: {
|
||||
$gt: hvSt.getTime(),
|
||||
},
|
||||
});
|
||||
|
||||
logger.info(`Destroyed scores.`, { r });
|
||||
|
||||
for (const userID of userIDs) {
|
||||
logger.info(`Reprocessing PBs for ${userID}`);
|
||||
|
||||
for (const chartID of chartIDs) {
|
||||
const scores = await db.scores.find({
|
||||
chartID,
|
||||
userID,
|
||||
});
|
||||
|
||||
if (scores.length === 0) {
|
||||
await db["personal-bests"].remove({
|
||||
chartID,
|
||||
userID,
|
||||
});
|
||||
} else {
|
||||
const pbDoc = await CreatePBDoc(userID, chartID, logger);
|
||||
|
||||
await db["personal-bests"].update(
|
||||
{
|
||||
chartID,
|
||||
userID,
|
||||
},
|
||||
{
|
||||
$set: pbDoc,
|
||||
},
|
||||
{
|
||||
upsert: true,
|
||||
}
|
||||
);
|
||||
|
||||
await UpdateChartRanking(chartID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info(`Done`);
|
||||
})();
|
||||
@@ -1,18 +0,0 @@
|
||||
import db from "external/mongo/db";
|
||||
|
||||
(async () => {
|
||||
const charts = await db.charts.chunithm.find({});
|
||||
|
||||
for (const c of charts) {
|
||||
await db.charts.chunithm.update(
|
||||
{
|
||||
_id: c._id,
|
||||
},
|
||||
{
|
||||
$set: {
|
||||
"data.inGameID": c.songID,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
})();
|
||||
@@ -1,55 +0,0 @@
|
||||
import db from "external/mongo/db";
|
||||
|
||||
(async () => {
|
||||
await db.scores.update(
|
||||
{ game: "sdvx", "scoreData.lamp": "ULTIMATE CHAIN" },
|
||||
{
|
||||
$set: {
|
||||
"scoreData.judgements.miss": 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
multi: true,
|
||||
}
|
||||
);
|
||||
|
||||
await db["personal-bests"].update(
|
||||
{ game: "sdvx", "scoreData.lamp": "ULTIMATE CHAIN" },
|
||||
{
|
||||
$set: {
|
||||
"scoreData.judgements.miss": 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
multi: true,
|
||||
}
|
||||
);
|
||||
|
||||
await db.scores.update(
|
||||
{ game: "sdvx", "scoreData.lamp": "PERFECT ULTIMATE CHAIN" },
|
||||
{
|
||||
$set: {
|
||||
"scoreData.judgements.miss": 0,
|
||||
"scoreData.judgements.near": 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
multi: true,
|
||||
}
|
||||
);
|
||||
|
||||
await db["personal-bests"].update(
|
||||
{ game: "sdvx", "scoreData.lamp": "PERFECT ULTIMATE CHAIN" },
|
||||
{
|
||||
$set: {
|
||||
"scoreData.judgements.miss": 0,
|
||||
"scoreData.judgements.near": 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
multi: true,
|
||||
}
|
||||
);
|
||||
|
||||
process.exit(0);
|
||||
})();
|
||||
@@ -1,32 +0,0 @@
|
||||
import db from "external/mongo/db";
|
||||
|
||||
if (require.main === module) {
|
||||
(async () => {
|
||||
const ugs = await db["user-goals"].find(
|
||||
{},
|
||||
{
|
||||
projectID: true,
|
||||
}
|
||||
);
|
||||
|
||||
for (const ug of ugs) {
|
||||
await db["user-goals"].update(
|
||||
{
|
||||
_id: ug._id,
|
||||
},
|
||||
{
|
||||
$set: {
|
||||
progressHuman: ug.progressHuman.toString(),
|
||||
outOfHuman: ug.outOfHuman.toString(),
|
||||
lastInteraction: null,
|
||||
},
|
||||
$unset: {
|
||||
note: 1,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
process.exit(0);
|
||||
})();
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import db from "external/mongo/db";
|
||||
import fs from "fs";
|
||||
|
||||
(async () => {
|
||||
const all = await db.songs.sdvx.find({});
|
||||
|
||||
const humanise = [];
|
||||
for (const h of all) {
|
||||
if (!h.title.match(/^[a-zA-Z0-9 ().!?-_]*$/)) {
|
||||
humanise.push(h);
|
||||
}
|
||||
}
|
||||
|
||||
fs.writeFileSync(
|
||||
"needs-humanise.csv",
|
||||
humanise
|
||||
.map(
|
||||
(e) =>
|
||||
`${e.id}, "${e.title.replace('"', '\\"')}", "${e.artist.replace('"', '\\"')}"`
|
||||
)
|
||||
.join("\n")
|
||||
);
|
||||
|
||||
process.exit(0);
|
||||
})();
|
||||
@@ -1,21 +0,0 @@
|
||||
import db from "external/mongo/db";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { StaticConfig } from "tachi-common";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
(async () => {
|
||||
for (const game of StaticConfig.allSupportedGames) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await db.songs[game].update(
|
||||
{},
|
||||
{ $rename: { "alt-titles": "altTitles", "search-titles": "searchTerms" } },
|
||||
{ multi: true }
|
||||
);
|
||||
|
||||
logger.info(`Refactored title names for ${game}.`);
|
||||
}
|
||||
|
||||
logger.info(`Done.`);
|
||||
process.exit(0);
|
||||
})();
|
||||
@@ -1,171 +0,0 @@
|
||||
import db from "external/mongo/db";
|
||||
import fs from "fs";
|
||||
import {
|
||||
USC_DEFAULT_HOLD,
|
||||
USC_DEFAULT_MISS,
|
||||
USC_DEFAULT_NEAR,
|
||||
USC_DEFAULT_PERFECT,
|
||||
USC_DEFAULT_SLAM,
|
||||
} from "lib/constants/usc-ir";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { OrphanScore } from "lib/score-import/framework/orphans/orphans";
|
||||
import UpdateScore from "lib/score-mutation/update-score";
|
||||
import { integer, ScoreDocument } from "tachi-common";
|
||||
import { DeleteScore } from "lib/score-mutation/delete-scores";
|
||||
import { UpdateAllPBs } from "utils/calculations/recalc-scores";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
const oldChartIDtoSHA1 = JSON.parse(fs.readFileSync(`${__dirname}/usc-map.json`, "utf-8"));
|
||||
|
||||
if (require.main === module) {
|
||||
(async () => {
|
||||
const keep = await db.charts.usc.find(
|
||||
{ "data.hashSHA1": { $in: Object.values(oldChartIDtoSHA1) } },
|
||||
{ projection: { chartID: 1, "data.hashSHA1": 1, songID: 1, playtype: 1 } }
|
||||
);
|
||||
|
||||
// @ts-expect-error asdf
|
||||
const keepHashes = keep.map((e) => e.data.hashSHA1);
|
||||
|
||||
const keepChartIDs = Object.entries(oldChartIDtoSHA1)
|
||||
.filter(([, v]) => keepHashes.includes(v))
|
||||
.map(([k]) => k);
|
||||
|
||||
const rmScores = (await db.scores.find({
|
||||
game: "usc",
|
||||
chartID: { $nin: keepChartIDs },
|
||||
})) as ScoreDocument<"usc:Controller" | "usc:Keyboard">[];
|
||||
|
||||
logger.info(`Re-orphaning and unseating ${rmScores.length} scores.`);
|
||||
|
||||
let i = 0;
|
||||
for (const score of rmScores) {
|
||||
i++;
|
||||
if (i % 100 === 0) {
|
||||
logger.info(`${i}/${rmScores.length}...`);
|
||||
}
|
||||
|
||||
const chartSHA1 = oldChartIDtoSHA1[score.chartID];
|
||||
|
||||
if (!chartSHA1) {
|
||||
logger.warn(`Can't find a chartsha1 for ${score.chartID}?`);
|
||||
continue;
|
||||
}
|
||||
|
||||
await ReOrphanScore(score, chartSHA1);
|
||||
await DeleteScore(score, false, false);
|
||||
}
|
||||
|
||||
const keepScores = await db.scores.find({
|
||||
game: "usc",
|
||||
chartID: { $in: keepChartIDs },
|
||||
});
|
||||
logger.info(`Keeping and migrating ${keepScores.length} scores.`);
|
||||
|
||||
const sha1ToChartID = Object.fromEntries(
|
||||
keep.map((e) => [
|
||||
// @ts-expect-error hashsha1 exists i'm just lazy
|
||||
`${e.data.hashSHA1}:${e.playtype}`,
|
||||
{ chartID: e.chartID, songID: e.songID },
|
||||
])
|
||||
) as { [key: string]: { chartID: string; songID: integer } };
|
||||
|
||||
let j = 0;
|
||||
for (const score of keepScores) {
|
||||
j++;
|
||||
if (j % 100 === 0) {
|
||||
logger.info(`${j}/${keepScores.length}`);
|
||||
}
|
||||
|
||||
const sha1 = oldChartIDtoSHA1[score.chartID];
|
||||
const newChartID = sha1ToChartID[`${sha1}:${score.playtype}`].chartID;
|
||||
const newSongID = sha1ToChartID[`${sha1}:${score.playtype}`].songID;
|
||||
|
||||
if (!newChartID) {
|
||||
logger.error(
|
||||
`Couldn't resolve old:${score.chartID} -> sha1:${sha1} (playtype: ${score.playtype}) -> new:${newChartID}?`
|
||||
);
|
||||
|
||||
throw new Error("panic");
|
||||
}
|
||||
|
||||
await UpdateScore(
|
||||
score,
|
||||
Object.assign({}, score, { songID: newSongID, chartID: newChartID }),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
// You'd think the update scripts don't result in pbs that point to
|
||||
// dead charts, but they do.
|
||||
logger.info(`Reloading USC PBs.`);
|
||||
await db["personal-bests"].remove({ game: "usc" });
|
||||
await UpdateAllPBs(undefined, { game: "usc" });
|
||||
|
||||
logger.info(`Done.`);
|
||||
|
||||
process.exit(0);
|
||||
})();
|
||||
}
|
||||
|
||||
function ReOrphanScore(sc: ScoreDocument<"usc:Controller" | "usc:Keyboard">, chartSHA1: string) {
|
||||
let mirror = false;
|
||||
let random = false;
|
||||
|
||||
if (sc.scoreMeta.noteMod === "MIR-RAN") {
|
||||
mirror = true;
|
||||
random = false;
|
||||
} else if (sc.scoreMeta.noteMod === "RANDOM") {
|
||||
random = true;
|
||||
} else if (sc.scoreMeta.noteMod === "MIRROR") {
|
||||
mirror = true;
|
||||
}
|
||||
|
||||
const gaugeType =
|
||||
sc.scoreMeta.gaugeMod === "NORMAL"
|
||||
? 0
|
||||
: sc.scoreMeta.gaugeMod === "HARD"
|
||||
? 1
|
||||
: sc.scoreMeta.gaugeMod === "PERMISSIVE"
|
||||
? 2
|
||||
: 0;
|
||||
|
||||
return OrphanScore(
|
||||
"ir/usc",
|
||||
sc.userID,
|
||||
{
|
||||
combo: sc.scoreData.hitMeta.maxCombo ?? null,
|
||||
crit: sc.scoreData.judgements.critical!,
|
||||
near: sc.scoreData.judgements.near!,
|
||||
error: sc.scoreData.judgements.miss!,
|
||||
early: sc.scoreData.hitMeta.fast ?? null,
|
||||
late: sc.scoreData.hitMeta.slow ?? null,
|
||||
gauge: sc.scoreData.hitMeta.gauge!,
|
||||
options: {
|
||||
autoFlags: 0,
|
||||
gaugeOpt: 0,
|
||||
gaugeType,
|
||||
mirror,
|
||||
random,
|
||||
},
|
||||
score: sc.scoreData.score,
|
||||
timestamp: sc.timeAchieved!,
|
||||
windows: {
|
||||
perfect: USC_DEFAULT_PERFECT,
|
||||
good: USC_DEFAULT_NEAR,
|
||||
hold: USC_DEFAULT_HOLD,
|
||||
miss: USC_DEFAULT_MISS,
|
||||
slam: USC_DEFAULT_SLAM,
|
||||
},
|
||||
},
|
||||
{
|
||||
chartHash: chartSHA1,
|
||||
playtype: sc.playtype,
|
||||
timeReceived: sc.timeAchieved!,
|
||||
},
|
||||
`Lost parent as a result of USC migration.`,
|
||||
"usc",
|
||||
logger
|
||||
);
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
import db from "external/mongo/db";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { GetGradeFromPercent } from "lib/score-import/framework/common/score-utils";
|
||||
import UpdateScore from "lib/score-mutation/update-score";
|
||||
import { ChartDocument, GetGamePTConfig } from "tachi-common";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
if (require.main === module) {
|
||||
let i = 0;
|
||||
db.scores
|
||||
.find({ game: "chunithm", "scoreData.grade": null })
|
||||
// @ts-expect-error dumb
|
||||
.each(async (oldScore, { pause, resume }) => {
|
||||
pause();
|
||||
|
||||
const chart = (await db.charts.chunithm.findOne({
|
||||
chartID: oldScore.chartID,
|
||||
})) as ChartDocument<"chunithm:Single">;
|
||||
|
||||
if (!chart) {
|
||||
logger.severe(`Chart ${oldScore.chartID} has no chart?`);
|
||||
return resume();
|
||||
}
|
||||
|
||||
const newScore = JSON.parse(JSON.stringify(oldScore));
|
||||
|
||||
newScore.scoreData.grade = GetGradeFromPercent(
|
||||
"chunithm",
|
||||
oldScore.playtype,
|
||||
oldScore.scoreData.percent
|
||||
);
|
||||
|
||||
newScore.scoreData.gradeIndex = GetGamePTConfig(
|
||||
"chunithm",
|
||||
oldScore.playtype
|
||||
).grades.indexOf(newScore.scoreData.grade);
|
||||
|
||||
await UpdateScore(oldScore, newScore);
|
||||
|
||||
i++;
|
||||
|
||||
resume();
|
||||
})
|
||||
.then(() => {
|
||||
logger.info(`Fixed ${i} bad scores.`);
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
import db from "external/mongo/db";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { GetGradeFromPercent } from "lib/score-import/framework/common/score-utils";
|
||||
import UpdateScore from "lib/score-mutation/update-score";
|
||||
import { ChartDocument, GetGamePTConfig } from "tachi-common";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
if (require.main === module) {
|
||||
(async () => {
|
||||
let i = 0;
|
||||
db.scores
|
||||
.find({ game: "iidx" })
|
||||
// @ts-expect-error dumb
|
||||
.each(async (oldScore, { pause, resume }) => {
|
||||
pause();
|
||||
|
||||
const chart = (await db.charts.iidx.findOne({
|
||||
chartID: oldScore.chartID,
|
||||
})) as ChartDocument<"iidx:SP">;
|
||||
|
||||
if (!chart) {
|
||||
logger.severe(`Chart ${oldScore.chartID} has no chart?`);
|
||||
return resume();
|
||||
}
|
||||
|
||||
const percent = (100 * oldScore.scoreData.score) / (chart.data.notecount * 2);
|
||||
if (Math.abs(percent - oldScore.scoreData.percent) > 0.00001) {
|
||||
const newScore = JSON.parse(JSON.stringify(oldScore));
|
||||
|
||||
newScore.scoreData.percent = percent;
|
||||
newScore.scoreData.grade = GetGradeFromPercent(
|
||||
"iidx",
|
||||
oldScore.playtype,
|
||||
percent
|
||||
);
|
||||
newScore.scoreData.gradeIndex = GetGamePTConfig(
|
||||
"iidx",
|
||||
oldScore.playtype
|
||||
).grades.indexOf(newScore.scoreData.grade);
|
||||
|
||||
await UpdateScore(oldScore, newScore);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
resume();
|
||||
})
|
||||
.then(() => {
|
||||
logger.info(`Fixed ${i} bad scores.`);
|
||||
process.exit(0);
|
||||
});
|
||||
})();
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import db from "external/mongo/db";
|
||||
|
||||
if (require.main === module) {
|
||||
(async () => {
|
||||
const badScoreInfos = await db.sessions.find({
|
||||
"scoreInfo.isNewScore": false,
|
||||
"scoreInfo.scoreDelta": null,
|
||||
});
|
||||
|
||||
for (const session of badScoreInfos) {
|
||||
const scoreInfo = session.scoreInfo.filter(
|
||||
(e) => !(!e.isNewScore && e.scoreDelta === null)
|
||||
);
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await db.sessions.update(
|
||||
{
|
||||
sessionID: session.sessionID,
|
||||
},
|
||||
{
|
||||
$set: {
|
||||
scoreInfo,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
process.exit(0);
|
||||
})();
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { PushToS3 } from "lib/cdn/s3";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
if (require.main === module) {
|
||||
(async () => {
|
||||
logger.info("Starting request.");
|
||||
|
||||
const res = await PushToS3("debug/testfile", "foo.txt");
|
||||
|
||||
logger.info("Request done.", res);
|
||||
|
||||
process.exit(0);
|
||||
})();
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
import UpdateIsPrimaryStatus from "lib/score-mutation/update-isprimary";
|
||||
|
||||
UpdateIsPrimaryStatus().then(() => process.exit(0));
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,7 @@ import { Command } from "commander";
|
||||
import { Databases, monkDB } from "external/mongo/db";
|
||||
import { DatabaseSchemas } from "external/mongo/schemas";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { PrudenceError } from "prudence";
|
||||
import { FormatPrError } from "utils/prudence";
|
||||
|
||||
const program = new Command();
|
||||
@@ -33,7 +34,7 @@ export async function ValidateCollection(collectionName: Databases): Promise<voi
|
||||
schemaRunner(c);
|
||||
success++;
|
||||
} catch (err) {
|
||||
logger.error(`[${collectionName}]: ${FormatPrError(err)}`, c);
|
||||
logger.error(`[${collectionName}]: ${FormatPrError(err as PrudenceError)}`, c);
|
||||
fails++;
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user