208 lines
4.8 KiB
TypeScript
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}...`);
|
|
});
|