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 */ for(const type in types) { sqlite.exec( ` CREATE TABLE IF NOT EXISTS "${type}" ( "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 "${type}" ( rank, name, points ) VALUES (?, ?, ?)`).run( rank, entry[0], entry[1]) ++rank } } /* Generate indexes */ for(const type in types) { sqlite.exec(`CREATE INDEX IF NOT EXISTS "idx_${type}_player" ON "${type}" ("Name")`) sqlite.exec(`CREATE INDEX IF NOT EXISTS "Idx_${type}_rank" on "${type}" ("Rank")`) } } export default { processAllPoints, processRankings, processTeamRankings }