Skip to content

Commit

Permalink
Rename analytics and add ranking queries
Browse files Browse the repository at this point in the history
  • Loading branch information
nlinnanen committed May 5, 2024
1 parent d5b5b38 commit f696efd
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 37 deletions.
29 changes: 29 additions & 0 deletions src/analytics/rankings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { prisma } from "../../config";

const topUsersByGuild = async (guild: string, limit: number) => {
const topUsers = await prisma.$queryRaw`
SELECT
"userId",
"telegramUsername",
"firstName",
"lastName",
SUM("earnedPoints") as "totalPoints",
COUNT(*) as "totalEntries"
FROM
"Entry" JOIN "User" ON "Entry"."userId" = "User"."telegramUserId"
WHERE
"guild" = ${guild}
GROUP BY
"userId",
"telegramUsername",
"firstName",
"lastName"
ORDER BY
"totalPoints" DESC
LIMIT
${limit}
`;
return topUsers;
}

export default topUsersByGuild;
2 changes: 1 addition & 1 deletion src/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const COEFFICIENTS: Record<Sport, number> = {
cycle: 0.2,
};
// The limit for the number of points that is needed to achieve the milestone
export const MILESTONE_LIMIT = 50;
export const MILESTONE_LIMIT = 400;

export const INVALID_INPUT_STICKERS = [
"CAACAgQAAxkBAAIDpGPZi6i22MLQy6eNj5DQEFhhv03uAAJkAAOBtmEJhHIBjFv2YK4tBA",
Expand Down
66 changes: 66 additions & 0 deletions src/server/analytics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import express from 'express';
import { validatePeriod } from './middleware';
import { calculateGuildStatistics } from '../analytics/statistics';
import topUsersByGuild from '../analytics/rankings';
import { arrayToCSV } from '../common/utils';

const router = express.Router({mergeParams: true});

export interface StatisticsResponse extends express.Response {
locals: {
guild: string;
periodStart: Date;
periodEnd: Date;
};
}

router.get('/ranking/:guild', async (req, res: StatisticsResponse) => {
if (req.query.pass !== process.env.ADMIN_PASSWORD) {
console.log("Wrong password");
return res.status(401).send("Wrong password!");
}

const guild = req.params.guild;
if (!req.query.limit || ! ((typeof req.query.limit) === 'string')) {
return res.status(400).send('Limit query parameter is required as a string');
}
const limit = Number.parseInt(req.query.limit as string ?? '10');
try {
const topUsers = await topUsersByGuild(guild, limit) as Record<string, unknown>[];
const csv = arrayToCSV([
"userId",
"telegramUsername",
"firstName",
"lastName",
"totalPoints",
"totalEntries"
], topUsers);
res.header("Content-Type", "text/csv");
res.status(200).send(csv);
} catch (error) {
console.error(error);
res.status(500).send('An error occurred while calculating rankings');
}
});

// Middleware to validate the period start and end query parameters
router.use(validatePeriod);

router.get('/statistics', async (req, res: StatisticsResponse) => {
if (req.query.pass !== process.env.ADMIN_PASSWORD) {
console.log("Wrong password");
return res.status(401).send("Wrong password!");
}

const { periodStart, periodEnd } = res.locals;
try {
const statistics = await calculateGuildStatistics(periodStart, periodEnd);
res.json(Object.fromEntries(statistics));
} catch (error) {
console.error(error);
res.status(500).send('An error occurred while calculating statistics');
}
});


export default router;
34 changes: 0 additions & 34 deletions src/server/analytics/statistics.ts

This file was deleted.

4 changes: 2 additions & 2 deletions src/server/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import express from "express";
import { saveEntriesAsCSV } from "../entries";
import statisticsRouter from "./analytics/statistics";
import analyticsRouter from "./analytics";

// biome-ignore lint/style/noNonNullAssertion: <explanation>
const port = Number.parseInt(process.env.PORT!);
Expand Down Expand Up @@ -29,7 +29,7 @@ app.get("/entries", async (req, res) => {
res.status(200).send(fs.readFileSync("./entries.csv"));
});

app.use("/statistics", statisticsRouter);
app.use("/analytics", analyticsRouter);

export const launchServer = async () => {
app.listen(port, () => console.log("Running on port ", port));
Expand Down
File renamed without changes.

0 comments on commit f696efd

Please sign in to comment.