From 0db3240f58a589d25e288e42963b6e24d41d6d27 Mon Sep 17 00:00:00 2001 From: Michael C Date: Mon, 27 Dec 2021 04:48:07 -0500 Subject: [PATCH] add getTopCategoryUsers --- src/app.ts | 3 ++ src/routes/getTopCategoryUsers.ts | 67 +++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 src/routes/getTopCategoryUsers.ts diff --git a/src/app.ts b/src/app.ts index 23ed171..04415ba 100644 --- a/src/app.ts +++ b/src/app.ts @@ -46,6 +46,8 @@ import { getChapterNames } from "./routes/getChapterNames"; import { postRating } from "./routes/ratings/postRating"; import { getRating } from "./routes/ratings/getRating"; import { postClearCache as ratingPostClearCache } from "./routes/ratings/postClearCache"; +import { getTopCategoryUsers } from "./routes/getTopCategoryUsers"; +import path from "path"; export function createServer(callback: () => void): Server { // Create a service (the app object is just a callback). @@ -128,6 +130,7 @@ function setupRoutes(router: Router) { router.get("/api/getSavedTimeForUser", getSavedTimeForUser); router.get("/api/getTopUsers", getTopUsers); + router.get("/api/getTopCategoryUsers", getTopCategoryUsers); //send out totals //send the total submissions, total views and total minutes saved diff --git a/src/routes/getTopCategoryUsers.ts b/src/routes/getTopCategoryUsers.ts new file mode 100644 index 0000000..5ea135b --- /dev/null +++ b/src/routes/getTopCategoryUsers.ts @@ -0,0 +1,67 @@ +import { db } from "../databases/databases"; +import { createMemoryCache } from "../utils/createMemoryCache"; +import { config } from "../config"; +import { Request, Response } from "express"; + +const MILLISECONDS_IN_MINUTE = 60000; +const getTopCategoryUsersWithCache = createMemoryCache(generateTopCategoryUsersStats, config.getTopUsersCacheTimeMinutes * MILLISECONDS_IN_MINUTE); +const maxRewardTimePerSegmentInSeconds = config.maxRewardTimePerSegmentInSeconds ?? 86400; + +async function generateTopCategoryUsersStats(sortBy: string, category: string) { + + const userNames = []; + const viewCounts = []; + const totalSubmissions = []; + const minutesSaved = []; + + const rows = await db.prepare("all", `SELECT COUNT(*) as "totalSubmissions", SUM(views) as "viewCount", + SUM(((CASE WHEN "sponsorTimes"."endTime" - "sponsorTimes"."startTime" > ? THEN ? ELSE "sponsorTimes"."endTime" - "sponsorTimes"."startTime" END) / 60) * "sponsorTimes"."views") as "minutesSaved", + SUM("votes") as "userVotes", COALESCE("userNames"."userName", "sponsorTimes"."userID") as "userName" FROM "sponsorTimes" LEFT JOIN "userNames" ON "sponsorTimes"."userID"="userNames"."userID" + LEFT JOIN "shadowBannedUsers" ON "sponsorTimes"."userID"="shadowBannedUsers"."userID" + WHERE category = ? AND "sponsorTimes"."votes" > -1 AND "sponsorTimes"."shadowHidden" != 1 AND "shadowBannedUsers"."userID" IS NULL + GROUP BY COALESCE("userName", "sponsorTimes"."userID") HAVING SUM("votes") > 20 + ORDER BY "${sortBy}" DESC LIMIT 100`, [category, maxRewardTimePerSegmentInSeconds, maxRewardTimePerSegmentInSeconds]); + + for (let i = 0; i < rows.length; i++) { + userNames[i] = rows[i].userName; + + viewCounts[i] = rows[i].viewCount; + totalSubmissions[i] = rows[i].totalSubmissions; + minutesSaved[i] = rows[i].minutesSaved; + } + + return { + userNames, + viewCounts, + totalSubmissions, + minutesSaved + }; +} + +export async function getTopCategoryUsers(req: Request, res: Response): Promise { + const sortType = parseInt(req.query.sortType as string); + const category = req.query.category as string; + + if (sortType == undefined || config.categoryList.includes(category) ) { + //invalid request + return res.sendStatus(400); + } + + //setup which sort type to use + let sortBy = ""; + if (sortType == 0) { + sortBy = "minutesSaved"; + } else if (sortType == 1) { + sortBy = "viewCount"; + } else if (sortType == 2) { + sortBy = "totalSubmissions"; + } else { + //invalid request + return res.sendStatus(400); + } + + const stats = await getTopCategoryUsersWithCache(sortBy, category); + + //send this result + return res.send(stats); +}