Files
sous-podzim2024-app/src/index.ts
2024-09-21 00:53:18 +02:00

208 lines
4.8 KiB
TypeScript

import express from "express";
import ejs from "ejs";
import multer from "multer";
import { db } from "./database/db";
import { eq, sql } from "drizzle-orm";
import { personTable, pointsTable } from "./database/schema";
import calculateNewPoints from "./gambleMath";
const app = express();
const port = 8080;
const upload = multer();
//app.use(express.urlencoded);
app.use(express.static('www'));
app.get("/", async (req, res) => {
const people = await db.select({
personId: personTable.personId,
name: personTable.name
}).from(personTable)
.leftJoin(pointsTable, eq(personTable.personId, pointsTable.personId))
.groupBy(personTable.personId)
ejs.renderFile('src/templates/index.ejs', { people: people }, function (err, str) {
if (err) {
res.status(500).send(err);
}
res.send(str);
});
});
function getNextGambleTime(time: Date): Date {
return new Date(time.getTime() + 3 * 60 * 60 * 1000);
}
function isGambleAvailable(time: Date | null): boolean {
if (time == null) {
return true;
}
// 3 hour delay before showing
if (getNextGambleTime(time) < new Date()) {
return true;
}
return false;
}
function isDetailAvailable(time: Date | null): boolean {
if (time == null) {
return false;
}
// 2 minute delay before hiding
if (new Date(time.getTime() + 2 * 60 * 1000) > new Date()) {
return true;
}
return false;
}
function sendError(res: express.Response, code: number, error: string): void {
ejs.renderFile('src/templates/error.ejs', { error: error }, function (err, str) {
if (err) {
res.status(500).send(err);
}
res.status(code).send(str);
});
}
app.get("/gamble/:id", async (req, res) => {
let id = parseInt(req.params.id);
if (id == undefined) {
res.status(404).send("Invalid person id");
return;
}
let person = await db.query.personTable.findFirst({
where: eq(personTable.personId, id)
})
if (!person) {
res.status(404).send("Invalid person id");
return;
}
if (isDetailAvailable(person.gambleTime)) {
res.redirect('/person/' + id);
return;
}
if (!isGambleAvailable(person.gambleTime)) {
if (person.gambleTime == null) {
sendError(res, 423, "Gamble není dostupný");
} else {
sendError(res, 423, "Gamble bude dostupný až ve " + getNextGambleTime(person.gambleTime).toLocaleString('cs', {
hour: "2-digit",
minute: "2-digit",
}));
}
return;
}
ejs.renderFile('src/templates/gamble.ejs', { person: person }, function (err, str) {
if (err) {
res.status(500).send(err);
}
res.send(str);
});
});
app.post("/gamble/:id", upload.none(), async (req, res) => {
let id = parseInt(req.params.id);
if (id == undefined) {
res.status(404).send("Invalid person id");
return;
}
let person = (await db.select({
personId: personTable.personId,
name: personTable.name,
secret: personTable.secret,
gambleTime: personTable.gambleTime,
pointsTotal: sql<string>`coalesce(sum(${pointsTable.points}), 0)`
}).from(personTable)
.leftJoin(pointsTable, eq(personTable.personId, pointsTable.personId))
.where(eq(personTable.personId, id))
.groupBy(personTable.personId))[0];
if (!person) {
sendError(res, 404, "Osoba nenalezena");
return;
}
if (!isGambleAvailable(person.gambleTime)) {
sendError(res, 423, "Nelze zadat další gamble");
return;
}
if (person.secret != req.body['secret']) {
sendError(res, 423, "Nesprávé heslo");
return;
}
let currentPoints = parseInt(person.pointsTotal);
let newTotalPoints = calculateNewPoints(currentPoints);
let pointsDiff = newTotalPoints - currentPoints;
await db.update(personTable)
.set({
gambleTime: sql`NOW()`
})
.where(eq(personTable.personId, person.personId));
await db.insert(pointsTable).values({
personId: id,
points: pointsDiff
})
res.redirect('/person/' + id);
});
app.get("/person/:id", async (req, res) => {
let id = parseInt(req.params.id);
if (id == undefined) {
sendError(res, 404, "Osoba nenalezena");
return;
}
let person = (await db.select({
personId: personTable.personId,
name: personTable.name,
gambleTime: personTable.gambleTime,
pointsTotal: sql`coalesce(sum(${pointsTable.points}), 0)`
}).from(personTable)
.leftJoin(pointsTable, eq(personTable.personId, pointsTable.personId))
.where(eq(personTable.personId, id))
.groupBy(personTable.personId))[0];
if (!person) {
sendError(res, 404, "Osoba nenalezena");
return;
}
if (!isDetailAvailable(person.gambleTime)) {
sendError(res, 404, "Detail bude dostupný až po dalším gamblu");
}
let points = await db.query.pointsTable.findMany({
where: eq(pointsTable.personId, id)
});
ejs.renderFile('src/templates/person.ejs', { person: person, points: JSON.stringify(points) }, function (err, str) {
if (err) {
res.status(500).send(err);
}
res.send(str);
});
});
app.listen(port, () => {
console.log(`Listening on port ${port}...`);
});