From 0a817f6ea075bb09b5947bd8c67ced814f7a2149 Mon Sep 17 00:00:00 2001 From: zkldi Date: Thu, 27 May 2021 12:50:25 +0100 Subject: [PATCH] Course support --- server/pnpm-lock.yaml | 6 +- .../beatoraja/import-courses.ts | 10 ++ server/scripts/set-indexes.ts | 3 + server/src/external/mongo/db.ts | 2 + .../src/server/router/ir/beatoraja/router.ts | 109 +++++++++++++++++- 5 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 server/scripts/__JSON-TO-KTDB/beatoraja/import-courses.ts diff --git a/server/pnpm-lock.yaml b/server/pnpm-lock.yaml index b4d9d473c..af856296e 100644 --- a/server/pnpm-lock.yaml +++ b/server/pnpm-lock.yaml @@ -61,7 +61,7 @@ dependencies: express-session: 1.17.1 fast-json-stable-hash: 1.0.2 fast-xml-parser: 3.19.0 - kamaitachi-common: github.com/zkldi/Kamaitachi-common/2357b80b549c4f19fe7a92964f364b755238024e + kamaitachi-common: github.com/zkldi/Kamaitachi-common/eb24efe35fd5a24069386329404b2b477b2e14bf mongodb: 3.6.6 monk: 7.3.4 multer: 1.4.2 @@ -4344,8 +4344,8 @@ packages: engines: {node: '>=6'} dev: true - github.com/zkldi/Kamaitachi-common/2357b80b549c4f19fe7a92964f364b755238024e: - resolution: {tarball: https://codeload.github.com/zkldi/Kamaitachi-common/tar.gz/2357b80b549c4f19fe7a92964f364b755238024e} + github.com/zkldi/Kamaitachi-common/eb24efe35fd5a24069386329404b2b477b2e14bf: + resolution: {tarball: https://codeload.github.com/zkldi/Kamaitachi-common/tar.gz/eb24efe35fd5a24069386329404b2b477b2e14bf} name: kamaitachi-common version: 0.1.0 dependencies: diff --git a/server/scripts/__JSON-TO-KTDB/beatoraja/import-courses.ts b/server/scripts/__JSON-TO-KTDB/beatoraja/import-courses.ts new file mode 100644 index 000000000..fcf0ee58d --- /dev/null +++ b/server/scripts/__JSON-TO-KTDB/beatoraja/import-courses.ts @@ -0,0 +1,10 @@ +import fs from "fs"; +import path from "path"; + +import db from "../../../src/external/mongo/db"; + +(async () => { + const data = JSON.parse(fs.readFileSync(path.join(__dirname, "courses.json"), "utf-8")); + + await db["bms-course-lookup"].insert(data); +})(); diff --git a/server/scripts/set-indexes.ts b/server/scripts/set-indexes.ts index b43de190a..9f72fbfe8 100644 --- a/server/scripts/set-indexes.ts +++ b/server/scripts/set-indexes.ts @@ -82,6 +82,9 @@ const staticIndexes: Partial> = { ), index({ "data.hashSHA256": 1 }), ], + "bms-course-lookup": [index({ md5sums: 1 }, UNIQUE)], + "beatoraja-auth-tokens": [index({ token: 1 }, UNIQUE)], + "usc-auth-tokens": [index({ token: 1 }, UNIQUE)], }; const indexes: Partial> = staticIndexes; diff --git a/server/src/external/mongo/db.ts b/server/src/external/mongo/db.ts index 2c1e72264..8fd062d3e 100644 --- a/server/src/external/mongo/db.ts +++ b/server/src/external/mongo/db.ts @@ -24,6 +24,7 @@ import { UserGoalDocument, PBScoreDocument, UserMilestoneDocument, + BMSCourseDocument, } from "kamaitachi-common"; import monk from "monk"; import { MONGO_BASE_URL } from "../../lib/env/env"; @@ -117,6 +118,7 @@ const db = { "kai-auth-tokens": monkDB.get("kai-auth-tokens"), "usc-auth-tokens": monkDB.get("usc-auth-tokens"), "beatoraja-auth-tokens": monkDB.get("beatoraja-auth-tokens"), + "bms-course-lookup": monkDB.get("bms-course-lookup"), }; export default db; diff --git a/server/src/server/router/ir/beatoraja/router.ts b/server/src/server/router/ir/beatoraja/router.ts index d77e5c97a..fc6752101 100644 --- a/server/src/server/router/ir/beatoraja/router.ts +++ b/server/src/server/router/ir/beatoraja/router.ts @@ -4,6 +4,7 @@ import { SYMBOL_KtchiData } from "../../../../lib/constants/ktchi"; import CreateLogCtx, { KtLogger } from "../../../../lib/logger/logger"; import { ExpressWrappedScoreImportMain } from "../../../../lib/score-import/framework/express-wrapper"; import { ParseBeatorajaSingle } from "../../../../lib/score-import/import-types/ir/beatoraja/parser"; +import { UpdateClassIfGreater } from "../../../../utils/class"; import { Random20Hex } from "../../../../utils/misc"; import { GetUserWithIDGuaranteed, @@ -137,7 +138,113 @@ router.post("/submit-score", async (req, res) => { * courses - all of which are dans. * @name POST /ir/beatoraja/submit-course */ -router.post("/submit-course", async (req, res) => {}); +router.post("/submit-course", async (req, res) => { + const charts = req.body.course?.charts; + + if (!charts || !Array.isArray(charts) || charts.length !== 4) { + return res.status(400).json({ + success: false, + description: `Invalid Course Submission.`, + }); + } + + const clear = req.body.score?.clear; + + if (!clear || clear === "Failed") { + return res.status(200).json({ + success: true, + description: "Class not updated.", + }); + } + + if (req.body.score?.lntype !== 0) { + return res.status(400).json({ + success: false, + description: "LN mode is the only supported mode for dans.", + }); + } + + // Constraints are a bit complicated. + // We only want to accept dans with the following + // beatoraja constraints - ["MIRROR","LR2_GAUGE"] or + // ["MIRROR", "LR2_GAUGE", "LN"]. + const constraint = req.body.course.constraint; + + if ( + !constraint || + !Array.isArray(constraint) || + (constraint.length !== 2 && constraint.length !== 3) + ) { + return res.status(400).json({ + success: false, + description: `Invalid constraints.`, + }); + } + + // If there are two constraints, check that they are + // MIRROR and LR2_GAUGE. + if (!constraint.includes("MIRROR") || !constraint.includes("LR2_GAUGE")) { + return res.status(400).json({ + success: false, + description: `Invalid constraints.`, + }); + } + + // If there are three constraints, check that the third + // is LN + if (constraint.length === 3) { + if (!constraint.includes("LN")) { + return res.status(400).json({ + success: false, + description: `Invalid Constraints.`, + }); + } + } + + // Combine the md5s into one string in their order. + const combinedMD5s = charts.map((e) => e.md5).join(); + + const course = await db["bms-course-lookup"].findOne({ + md5sums: combinedMD5s, + }); + + if (!course) { + return res.status(404).json({ + success: false, + description: `Unsupported course.`, + }); + } + + const userID = req[SYMBOL_KtchiData]!.beatorajaAuthDoc!.userID; + + const result = await UpdateClassIfGreater( + userID, + "bms", + course.playtype, + course.set, + course.value + ); + + if (result) { + return res.status(200).json({ + success: true, + description: "Successfully updated class.", + body: { + set: course.set, + value: course.value, + }, + }); + } + + return res.status(200).json({ + success: true, + description: "Class not updated.", + body: { + set: course.set, + value: course.value, + }, + }); +}); router.use("/charts/:chartSHA256", chartsRouter);