mirror of
https://github.com/zkldi/Tachi.git
synced 2026-10-02 03:48:14 +03:00
GPT Milestone Endpoints
This commit is contained in:
+1
-1
@@ -84,7 +84,7 @@
|
||||
"rimraf": "3.0.2",
|
||||
"safe-json-stringify": "1.2.0",
|
||||
"seq-logging": "1.1.1",
|
||||
"tachi-common": "0.7.7",
|
||||
"tachi-common": "0.7.8",
|
||||
"ts-node": "10.4.0",
|
||||
"tsconfig-paths": "3.12.0",
|
||||
"typescript": "4.5.5",
|
||||
|
||||
Generated
+4
-4
@@ -65,7 +65,7 @@ specifiers:
|
||||
safe-json-stringify: 1.2.0
|
||||
seq-logging: 1.1.1
|
||||
supertest: 6.2.2
|
||||
tachi-common: 0.7.7
|
||||
tachi-common: 0.7.8
|
||||
tap: 15.1.6
|
||||
ts-node: 10.4.0
|
||||
tsconfig-paths: 3.12.0
|
||||
@@ -112,7 +112,7 @@ dependencies:
|
||||
rimraf: 3.0.2
|
||||
safe-json-stringify: 1.2.0
|
||||
seq-logging: 1.1.1
|
||||
tachi-common: 0.7.7
|
||||
tachi-common: 0.7.8
|
||||
ts-node: 10.4.0_2615db9039ce432b4abf2fc39ef336ec
|
||||
tsconfig-paths: 3.12.0
|
||||
typescript: 4.5.5
|
||||
@@ -5363,8 +5363,8 @@ packages:
|
||||
engines: {node: '>= 0.4'}
|
||||
dev: true
|
||||
|
||||
/tachi-common/0.7.7:
|
||||
resolution: {integrity: sha512-WsV4bCKdhackC24aTt7vdJTz/IEdRHiSm3+NeDWlU3AOmdMQV8YTcMCjeNscTr4yoccjpRNNG/avs+h/fFLDeg==}
|
||||
/tachi-common/0.7.8:
|
||||
resolution: {integrity: sha512-rDT+scIl1WQacdPrEIvM7fenRvkdjEQwMJMBDz1Pf/VQoYvyBeRL0rxjHrd26L8qkg1yPhwVKhs9DZUMnt4QzA==}
|
||||
dependencies:
|
||||
'@types/mongodb': 3.6.18
|
||||
dev: false
|
||||
|
||||
@@ -59,7 +59,7 @@ export function CalculateMilestoneOutOf(milestone: MilestoneDocument) {
|
||||
|
||||
if (milestone.criteria.type === "all") {
|
||||
return goalIDs.length;
|
||||
} else if (milestone.criteria.type === "abs") {
|
||||
} else if (milestone.criteria.type === "total") {
|
||||
if (milestone.criteria.value === null) {
|
||||
throw new Error(
|
||||
`Invalid milestone ${milestone.milestoneID} - abs and null are not compatible.`
|
||||
@@ -67,17 +67,10 @@ export function CalculateMilestoneOutOf(milestone: MilestoneDocument) {
|
||||
}
|
||||
|
||||
return milestone.criteria.value!;
|
||||
} else if (milestone.criteria.type === "proportion") {
|
||||
if (milestone.criteria.value === null) {
|
||||
throw new Error(
|
||||
`Invalid milestone ${milestone.milestoneID} - proportion and null are not compatible.`
|
||||
);
|
||||
}
|
||||
|
||||
return Math.floor(milestone.criteria.value * goalIDs.length);
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
// @ts-expect-error Yeah obviously this shouldn't happen. Mayaswell throw though.
|
||||
`Invalid milestone.criteria.type of ${milestone.criteria.type} -- milestoneID ${milestone.milestoneID}`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ router.get("/:goalID", ResolveGoalID, async (req, res) => {
|
||||
*
|
||||
* @param userID - The userID to evaluate this goal against. Must be a player of this GPT.
|
||||
*
|
||||
* @name GET /api/v1/games/:game/:playtype/targets/goals/:goalID/evaluate
|
||||
* @name GET /api/v1/games/:game/:playtype/targets/goals/:goalID/evaluate-for
|
||||
*/
|
||||
router.get(
|
||||
"/:goalID/evaluate-for",
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
import { RequestHandler, Router } from "express";
|
||||
import db from "external/mongo/db";
|
||||
import { SYMBOL_TachiAPIAuth, SYMBOL_TachiData } from "lib/constants/tachi";
|
||||
import { EvaluateMilestoneProgress, GetGoalsInMilestone } from "lib/targets/milestones";
|
||||
import prValidate from "server/middleware/prudence-validate";
|
||||
import { FormatGame } from "tachi-common";
|
||||
import { AssignToReqTachiData } from "utils/req-tachi-data";
|
||||
import { GetUsersWithIDs, ResolveUser } from "utils/user";
|
||||
|
||||
const router: Router = Router({ mergeParams: true });
|
||||
|
||||
const ResolveMilestoneID: RequestHandler = async (req, res, next) => {
|
||||
const game = req[SYMBOL_TachiData]!.game!;
|
||||
const playtype = req[SYMBOL_TachiData]!.playtype!;
|
||||
const milestoneID = req.params.milestoneID;
|
||||
|
||||
const milestone = await db.milestones.findOne({
|
||||
milestoneID,
|
||||
game,
|
||||
playtype,
|
||||
});
|
||||
|
||||
if (!milestone) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
description: `A milestone with ID ${milestoneID} doesn't exist.`,
|
||||
});
|
||||
}
|
||||
|
||||
AssignToReqTachiData(req, { milestoneDoc: milestone });
|
||||
|
||||
return next();
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve information about this milestone and who is subscribed to it.
|
||||
*
|
||||
* @name GET /api/v1/games/:game/:playtype/targets/milestones/:milestoneID
|
||||
*/
|
||||
router.get("/:milestoneID", ResolveMilestoneID, async (req, res) => {
|
||||
const milestone = req[SYMBOL_TachiData]!.milestoneDoc!;
|
||||
|
||||
const milestoneSubs = await db["milestone-subs"].find({
|
||||
milestoneID: milestone.milestoneID,
|
||||
});
|
||||
|
||||
const users = await GetUsersWithIDs(milestoneSubs.map((e) => e.userID));
|
||||
|
||||
const goals = await GetGoalsInMilestone(milestone);
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
description: `Retrieved information about ${milestone.name}.`,
|
||||
body: {
|
||||
milestone,
|
||||
milestoneSubs,
|
||||
users,
|
||||
goals,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Evaluates a milestone upon a user, even if they aren't subscribed to it.
|
||||
*
|
||||
* @param userID - The userID to evaluate this goal against. Must be a player of this GPT.
|
||||
*
|
||||
* @name GET /api/v1/games/:game/:playtype/targets/milestones/:milestone-id/evaluate-for
|
||||
*/
|
||||
router.get(
|
||||
"/:milestoneID/evaluate-for",
|
||||
ResolveMilestoneID,
|
||||
prValidate({ userID: "string" }),
|
||||
async (req, res) => {
|
||||
const game = req[SYMBOL_TachiData]!.game!;
|
||||
const playtype = req[SYMBOL_TachiData]!.playtype!;
|
||||
|
||||
const userID = req.query.userID as string;
|
||||
|
||||
const user = await ResolveUser(userID);
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
description: `The user ${userID} does not exist.`,
|
||||
});
|
||||
}
|
||||
|
||||
const hasPlayed = await db["game-stats"].findOne({
|
||||
game,
|
||||
playtype,
|
||||
userID: user.id,
|
||||
});
|
||||
|
||||
if (!hasPlayed) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
description: `The user ${user.username} hasn't played ${FormatGame(
|
||||
game,
|
||||
playtype
|
||||
)}.`,
|
||||
});
|
||||
}
|
||||
|
||||
const milestone = req[SYMBOL_TachiData]!.milestoneDoc!;
|
||||
|
||||
const milestoneProgress = await EvaluateMilestoneProgress(user.id, milestone);
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
description: `Evaluated ${milestone.name} for ${user.username}.`,
|
||||
body: milestoneProgress,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
export default router;
|
||||
@@ -1,8 +1,10 @@
|
||||
import { Router } from "express";
|
||||
import goalsRouter from "./goals/router";
|
||||
import milestonesRouter from "./milestones/router";
|
||||
|
||||
const router: Router = Router({ mergeParams: true });
|
||||
|
||||
router.use("/goals", goalsRouter);
|
||||
router.use("/milestones", milestonesRouter);
|
||||
|
||||
export default router;
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ const router: Router = Router({ mergeParams: true });
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
/**
|
||||
* Retrieves this users' set goals.
|
||||
* Retrieves this users' set goals for this GPT.
|
||||
*
|
||||
* @name GET /api/v1/users/:userID/games/:game/:playtype/targets/goals
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user