ddstats-server/db/tasks.js
2021-10-31 20:46:43 +01:00

141 lines
4.0 KiB
JavaScript

import msgpack from '@msgpack/msgpack'
import fs from 'fs'
import { sqlite } from "./init.js"
/**
* This module parses the msgpack provided by DDNet...
* @module db/decodeMsgpack
*/
export function decodeMsgpack() {
const data = fs.readFileSync('players.msgpack')
const decoded = msgpack.decodeMulti(data, {wrap: true})
const order = ['categories', 'maps', 'totalPoints', 'pointsRanks', 'pointsThisWeek', 'pointsThisMonth', 'teamRankPoints', 'rankPoints', 'serverRanks']
let final = {}
let i = 0
for (const part of decoded) {
final[order[i]] = part
++i
}
return final
}
/**
* This generates rankings for each map...
* @module db/processRankings
*/
export function processRankings() {
const maps = sqlite.prepare(`SELECT map FROM maps`);
for (const map of maps.iterate()) {
sqlite.prepare(
`
INSERT INTO rankings
(
map, name, time, timestamp, rank, server
)
SELECT map, name, time, timestamp, rank, server
FROM (
SELECT rank() OVER w AS rank,
map,
timestamp,
NAME,
min(time) AS time,
server
FROM race
WHERE map = ?
GROUP BY NAME window w AS (ORDER BY time) ) AS a
ORDER BY rank
`).run(map.Map)
}
}
/**
* This generates teamrankings for each map...
* @module db/processTeamRankings
*/
export function processTeamRankings() {
const maps = sqlite.prepare(`SELECT map FROM maps`);
for (const map of maps.iterate()) {
sqlite.prepare(
`
INSERT INTO teamrankings
(
name, map, id, time, timestamp, server, teamrank
)
SELECT DISTINCT(r.NAME),
r.map, r.id, r.time, r.timestamp,
Substring(n.server, 1, 3),
dense_rank() OVER w AS rank
FROM ((
SELECT DISTINCT id
FROM teamrace
WHERE map = ?
ORDER BY time) AS l
)
LEFT JOIN teamrace AS r
ON l.id = r.id
INNER JOIN race AS n
ON r.map = n.map
AND r.NAME = n.NAME
AND r.time = n.time window w AS (ORDER BY r.time)
`).run(map.Map)
}
}
/**
* This inserts all types of points into a table...
* @module db/processAllPoints
*/
export function processAllPoints() {
const msgpack = decodeMsgpack()
let types = {
points: msgpack.pointsRanks,
pointsThisWeek: msgpack.pointsThisWeek,
pointsThisMonth: msgpack.pointsThisMonth,
pointsTeam: msgpack.teamRankPoints,
pointsRank: msgpack.rankPoints,
}
/* Generate tables */
sqlite.exec(
`
CREATE TABLE IF NOT EXISTS "points"
(
"type" varchar(16) NOT NULL,
"rank" INTEGER NOT NULL,
"name" varchar(16) NOT NULL,
"points" INTEGER NOT NULL);
`)
/* Insert data */
for(const type in types) {
let rank = 1
for (const entry of types[type]) {
sqlite.prepare(
`
INSERT INTO "points"
(
type, rank, name, points
) VALUES (?, ?, ?, ?)`).run(
type, rank, entry[0], entry[1])
++rank
}
}
/* Generate indexes */
sqlite.exec(`CREATE INDEX IF NOT EXISTS "idx_points_type" ON "points" ("type")`)
sqlite.exec(`CREATE INDEX IF NOT EXISTS "Idx_points_rank" on "points" ("rank")`)
sqlite.exec(`CREATE INDEX IF NOT EXISTS "Idx_points_name" on "points" ("name")`)
}
export default {
processAllPoints,
processRankings,
processTeamRankings
}