Add support for regional leaderboards
3
index.js
|
@ -14,6 +14,7 @@ import { generateDB } from './libs/database/generate.js'
|
||||||
import { dbInit } from './libs/database/init.js'
|
import { dbInit } from './libs/database/init.js'
|
||||||
import { getStats, setStat } from './libs/serverStats.js'
|
import { getStats, setStat } from './libs/serverStats.js'
|
||||||
import { downloadEssentialData } from './libs/download/dowload.js'
|
import { downloadEssentialData } from './libs/download/dowload.js'
|
||||||
|
import { ddnssStart } from './libs/ddnss/handler.js'
|
||||||
|
|
||||||
const start = Date.now()
|
const start = Date.now()
|
||||||
const log = initLog("[ MAIN ]")
|
const log = initLog("[ MAIN ]")
|
||||||
|
@ -50,3 +51,5 @@ const elapsed = Date.now() - start
|
||||||
log(`Took ${elapsed/1000} seconds to start the server!`)
|
log(`Took ${elapsed/1000} seconds to start the server!`)
|
||||||
|
|
||||||
Server.listen(process.env.PORT ?? 12345, () => log(`Server started and listening on port ${process.env.PORT}.`))
|
Server.listen(process.env.PORT ?? 12345, () => log(`Server started and listening on port ${process.env.PORT}.`))
|
||||||
|
|
||||||
|
//ddnssStart()
|
|
@ -78,7 +78,8 @@ export function generateDB() {
|
||||||
`CREATE INDEX IF NOT EXISTS "idx_rankings_rank" ON "rankings" ("rank")`,
|
`CREATE INDEX IF NOT EXISTS "idx_rankings_rank" ON "rankings" ("rank")`,
|
||||||
`CREATE INDEX IF NOT EXISTS "idx_rankings_player" ON "rankings" ("player")`,
|
`CREATE INDEX IF NOT EXISTS "idx_rankings_player" ON "rankings" ("player")`,
|
||||||
`CREATE INDEX IF NOT EXISTS "idx_rankings_finishes" ON "rankings" ("finishes")`,
|
`CREATE INDEX IF NOT EXISTS "idx_rankings_finishes" ON "rankings" ("finishes")`,
|
||||||
`CREATE INDEX IF NOT EXISTS "idx_rankings_mapRank" ON "rankings" ("map", "rank")`
|
`CREATE INDEX IF NOT EXISTS "idx_rankings_mapRank" ON "rankings" ("map", "rank")`,
|
||||||
|
`CREATE INDEX IF NOT EXISTS "idx_rankings_playerServer" ON "rankings" ("player", "server")`
|
||||||
])
|
])
|
||||||
|
|
||||||
log("Generating teamrace index...")
|
log("Generating teamrace index...")
|
||||||
|
@ -181,4 +182,5 @@ export function generateDB() {
|
||||||
"colorFeetHex" varchar(8) NOT NULL
|
"colorFeetHex" varchar(8) NOT NULL
|
||||||
)
|
)
|
||||||
`)
|
`)
|
||||||
|
skinDB.exec(`CREATE INDEX IF NOT EXISTS "idx_player" ON "skindata" ("player")`)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import decodeMsgpack from './decodeMsgpack.js'
|
import decodeMsgpack from './decodeMsgpack.js'
|
||||||
import { execMany } from './helper.js'
|
import { execMany } from './helper.js'
|
||||||
import { sqlite } from './init.js'
|
import { sqlite } from './init.js'
|
||||||
|
import { mapToRegion, playerServer } from './wrapper.js'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This generates rankings for each map...
|
* This generates rankings for each map...
|
||||||
|
@ -163,6 +164,7 @@ export function processAllPoints() {
|
||||||
CREATE TABLE IF NOT EXISTS "points"
|
CREATE TABLE IF NOT EXISTS "points"
|
||||||
(
|
(
|
||||||
"type" varchar(16) NOT NULL,
|
"type" varchar(16) NOT NULL,
|
||||||
|
"region" varchar(24) NOT NULL,
|
||||||
"rank" INTEGER NOT NULL,
|
"rank" INTEGER NOT NULL,
|
||||||
"player" varchar(16) NOT NULL,
|
"player" varchar(16) NOT NULL,
|
||||||
"points" INTEGER NOT NULL
|
"points" INTEGER NOT NULL
|
||||||
|
@ -178,25 +180,27 @@ export function processAllPoints() {
|
||||||
.prepare(`
|
.prepare(`
|
||||||
INSERT INTO "points"
|
INSERT INTO "points"
|
||||||
(
|
(
|
||||||
type, rank, player, points
|
type, region, rank, player, points
|
||||||
) VALUES (?, ?, ?, ?)
|
) VALUES (?, ?, ?, ?, ?)
|
||||||
`)
|
`)
|
||||||
.run(
|
.run(
|
||||||
type,
|
type,
|
||||||
|
mapToRegion(playerServer(entry[0])),
|
||||||
rank,
|
rank,
|
||||||
entry[0],
|
entry[0],
|
||||||
entry[1]
|
entry[1]
|
||||||
)
|
)
|
||||||
|
|
||||||
++rank
|
++rank
|
||||||
}
|
}
|
||||||
|
console.log(`${type} Done...`)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate indexes */
|
/* Generate indexes */
|
||||||
execMany([
|
execMany([
|
||||||
`CREATE INDEX IF NOT EXISTS "idx_points_type" ON "points" ("type")`,
|
`CREATE INDEX IF NOT EXISTS "idx_points_type" ON "points" ("type")`,
|
||||||
`CREATE INDEX IF NOT EXISTS "Idx_points_rank" on "points" ("rank")`,
|
`CREATE INDEX IF NOT EXISTS "idx_points_rank" on "points" ("rank")`,
|
||||||
`CREATE INDEX IF NOT EXISTS "Idx_points_name" on "points" ("player")`
|
`CREATE INDEX IF NOT EXISTS "idx_points_name" on "points" ("player")`
|
||||||
|
`CREATE INDEX IF NOT EXISTS "idx_points_name" on "points" ("region", "type")`
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { sqlite } from './init.js'
|
import { sqlite, skinDB } from './init.js'
|
||||||
import { simpleSanitize } from './searcher.js'
|
import { simpleSanitize } from './searcher.js'
|
||||||
/**
|
/**
|
||||||
* This function checks if a player exists
|
* This function checks if a player exists
|
||||||
|
@ -222,17 +222,32 @@ export function leaderboardRace(map, start, end) {
|
||||||
* (points, pointsRank, pointsTeam, pointsThisWeek, pointsThisMonth)
|
* (points, pointsRank, pointsTeam, pointsThisWeek, pointsThisMonth)
|
||||||
*
|
*
|
||||||
* @param {string} type Which type of points to fetch
|
* @param {string} type Which type of points to fetch
|
||||||
|
* @param {string} region Which region should be included (Global, Europe, Asia, SA, NA, Africa, ME, OLD, Other)
|
||||||
* @param {number} start At which rank the leaderboard should begin
|
* @param {number} start At which rank the leaderboard should begin
|
||||||
* @param {number} end At which rank the leaderboard should end
|
* @param {number} end At which rank the leaderboard should end
|
||||||
|
|
||||||
* @returns {array} An array containing the leaderboard
|
* @returns {array} An array containing the leaderboard
|
||||||
*/
|
*/
|
||||||
export function leaderboardPoints(type, start, end) {
|
export function leaderboardPoints(type, region, start, end) {
|
||||||
const leaderboard = sqlite.prepare(`
|
let output = []
|
||||||
SELECT rank, player, points FROM points WHERE type = ? AND rank >= ? AND rank <= ? ORDER BY rank`)
|
let leaderboard
|
||||||
.all(type, start, end)
|
|
||||||
|
|
||||||
return leaderboard
|
if(region == "Global") {
|
||||||
|
leaderboard = sqlite.prepare(`
|
||||||
|
SELECT rank, region, player, points FROM points WHERE type = ? AND rank >= ? AND rank <= ? ORDER BY rank`)
|
||||||
|
.all(type, start, end)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
leaderboard = sqlite.prepare(`
|
||||||
|
SELECT rank, region, player, points FROM points WHERE type = ? AND region = ? ORDER BY rank ASC LIMIT ?, ${end}`)
|
||||||
|
.all(type, region, start - 1)
|
||||||
|
}
|
||||||
|
for (const entry of leaderboard) {
|
||||||
|
let flag = skinDB.prepare(`SELECT flag FROM skindata WHERE player = ?`).get(entry.player)?.flag ?? "default"
|
||||||
|
|
||||||
|
output.push({ rank: entry.rank, player: entry.player, points: entry.points, region: entry.region, flag: flag })
|
||||||
|
}
|
||||||
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -376,6 +391,80 @@ export function searchMap(query, categories, stars, sortBy, order) {
|
||||||
|
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
Europe
|
||||||
|
/ RUS - Russia
|
||||||
|
/ GER - Germany
|
||||||
|
/ NLD - Netherlands
|
||||||
|
/ TUR - Turkey
|
||||||
|
/ POL - Poland
|
||||||
|
/ FRA - France
|
||||||
|
|
||||||
|
Asia
|
||||||
|
/ IND - INDIA
|
||||||
|
/ SGP - Singapore
|
||||||
|
/ CHN - China
|
||||||
|
/ JAP - Japan
|
||||||
|
/ KOR - South Korea
|
||||||
|
|
||||||
|
South America
|
||||||
|
/ COL - Columbia
|
||||||
|
/ ARG - Argentina
|
||||||
|
/ CHL - Chile
|
||||||
|
/ BRA - Brazil
|
||||||
|
|
||||||
|
North America
|
||||||
|
/ CAN - Cananda
|
||||||
|
/ USA - USA
|
||||||
|
|
||||||
|
Africa
|
||||||
|
/ ZAF - South Africa
|
||||||
|
|
||||||
|
Middle east
|
||||||
|
/ KSA/UAE/IRN
|
||||||
|
|
||||||
|
Others
|
||||||
|
/ CRI - Costa Rica
|
||||||
|
/ AUS - Australia
|
||||||
|
/ OLD ranks (NA/EU)
|
||||||
|
/ UNK - Some bugged ranks
|
||||||
|
|
||||||
|
*/
|
||||||
|
export function mapToRegion(srv) {
|
||||||
|
if(srv == "RUS" || srv == "GER" || srv == "NLD" || srv == "TUR" || srv == "POL" || srv == "FRA")
|
||||||
|
return "Europe"
|
||||||
|
|
||||||
|
if(srv == "IND" || srv == "SGP" || srv == "CHN" || srv == "JAP" || srv == "KOR")
|
||||||
|
return "Asia"
|
||||||
|
|
||||||
|
if(srv == "COL" || srv == "ARG" || srv == "CHL" || srv == "BRA")
|
||||||
|
return "SA"
|
||||||
|
|
||||||
|
if(srv == "CAN" || srv == "USA")
|
||||||
|
return "NA"
|
||||||
|
|
||||||
|
if(srv == "ZAF")
|
||||||
|
return "Africa"
|
||||||
|
|
||||||
|
/* Middle east */
|
||||||
|
if(srv == "KSA" || srv == "UAE" || srv == "IRN")
|
||||||
|
return "ME"
|
||||||
|
|
||||||
|
if(srv == "")
|
||||||
|
return "OLD"
|
||||||
|
|
||||||
|
return "Other"
|
||||||
|
}
|
||||||
|
|
||||||
|
export function playerServer(player) {
|
||||||
|
/* This can be undefined if a player has changed their name */
|
||||||
|
const server = sqlite.prepare(
|
||||||
|
`SELECT server, COUNT(server) as a FROM rankings WHERE player = ? GROUP BY server ORDER BY a DESC`)
|
||||||
|
.get(player)?.server ?? ""
|
||||||
|
|
||||||
|
return server
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
playerExists,
|
playerExists,
|
||||||
|
@ -393,4 +482,7 @@ export default {
|
||||||
leaderboardRace,
|
leaderboardRace,
|
||||||
leaderboardTeamrace,
|
leaderboardTeamrace,
|
||||||
categoryExists,
|
categoryExists,
|
||||||
|
|
||||||
|
mapToRegion,
|
||||||
|
playerServer,
|
||||||
}
|
}
|
|
@ -53,11 +53,11 @@ routes.get(
|
||||||
'/leaderboards',
|
'/leaderboards',
|
||||||
(req, res) => {
|
(req, res) => {
|
||||||
const leaderboards = {
|
const leaderboards = {
|
||||||
points: wrapper.leaderboardPoints("points", 1, 10),
|
points: wrapper.leaderboardPoints("points", "Global", 1, 10),
|
||||||
pointsRank: wrapper.leaderboardPoints("pointsRank", 1, 10),
|
pointsRank: wrapper.leaderboardPoints("pointsRank", "Global", 1, 10),
|
||||||
pointsTeam: wrapper.leaderboardPoints("pointsTeam", 1, 10),
|
pointsTeam: wrapper.leaderboardPoints("pointsTeam", "Global", 1, 10),
|
||||||
pointsThisWeek: wrapper.leaderboardPoints("pointsThisWeek", 1, 10),
|
pointsThisWeek: wrapper.leaderboardPoints("pointsThisWeek", "Global", 1, 10),
|
||||||
pointsThisMonth: wrapper.leaderboardPoints("pointsThisMonth", 1, 10)
|
pointsThisMonth: wrapper.leaderboardPoints("pointsThisMonth", "Global", 1, 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
tx(req, res)('pages/leaderboards.njk', { leaderboards }, true, { currentSection: "leaderboards" })
|
tx(req, res)('pages/leaderboards.njk', { leaderboards }, true, { currentSection: "leaderboards" })
|
||||||
|
|
BIN
static/countryflags/AD.png
Executable file
After Width: | Height: | Size: 2.4 KiB |
BIN
static/countryflags/AE.png
Executable file
After Width: | Height: | Size: 707 B |
BIN
static/countryflags/AF.png
Executable file
After Width: | Height: | Size: 2.5 KiB |
BIN
static/countryflags/AG.png
Executable file
After Width: | Height: | Size: 2.0 KiB |
BIN
static/countryflags/AI.png
Executable file
After Width: | Height: | Size: 2.3 KiB |
BIN
static/countryflags/AL.png
Executable file
After Width: | Height: | Size: 2.1 KiB |
BIN
static/countryflags/AM.png
Executable file
After Width: | Height: | Size: 636 B |
BIN
static/countryflags/AO.png
Executable file
After Width: | Height: | Size: 1.6 KiB |
BIN
static/countryflags/AR.png
Executable file
After Width: | Height: | Size: 1.4 KiB |
BIN
static/countryflags/AS.png
Executable file
After Width: | Height: | Size: 3.8 KiB |
BIN
static/countryflags/AT.png
Executable file
After Width: | Height: | Size: 723 B |
BIN
static/countryflags/AU.png
Executable file
After Width: | Height: | Size: 2.2 KiB |
BIN
static/countryflags/AW.png
Executable file
After Width: | Height: | Size: 1.1 KiB |
BIN
static/countryflags/AX.png
Executable file
After Width: | Height: | Size: 910 B |
BIN
static/countryflags/AZ.png
Executable file
After Width: | Height: | Size: 1.2 KiB |
BIN
static/countryflags/BA.png
Executable file
After Width: | Height: | Size: 2.0 KiB |
BIN
static/countryflags/BB.png
Executable file
After Width: | Height: | Size: 1.2 KiB |
BIN
static/countryflags/BD.png
Executable file
After Width: | Height: | Size: 1.0 KiB |
BIN
static/countryflags/BE.png
Executable file
After Width: | Height: | Size: 567 B |
BIN
static/countryflags/BF.png
Executable file
After Width: | Height: | Size: 982 B |
BIN
static/countryflags/BG.png
Executable file
After Width: | Height: | Size: 709 B |
BIN
static/countryflags/BH.png
Executable file
After Width: | Height: | Size: 1.3 KiB |
BIN
static/countryflags/BI.png
Executable file
After Width: | Height: | Size: 2.4 KiB |
BIN
static/countryflags/BJ.png
Executable file
After Width: | Height: | Size: 677 B |
BIN
static/countryflags/BL.png
Executable file
After Width: | Height: | Size: 6.6 KiB |
BIN
static/countryflags/BM.png
Executable file
After Width: | Height: | Size: 3.1 KiB |
BIN
static/countryflags/BN.png
Executable file
After Width: | Height: | Size: 3.7 KiB |
BIN
static/countryflags/BO.png
Executable file
After Width: | Height: | Size: 1.5 KiB |
BIN
static/countryflags/BR.png
Executable file
After Width: | Height: | Size: 2.5 KiB |
BIN
static/countryflags/BS.png
Executable file
After Width: | Height: | Size: 1.1 KiB |
BIN
static/countryflags/BT.png
Executable file
After Width: | Height: | Size: 4.0 KiB |
BIN
static/countryflags/BW.png
Executable file
After Width: | Height: | Size: 639 B |
BIN
static/countryflags/BY.png
Executable file
After Width: | Height: | Size: 1.7 KiB |
BIN
static/countryflags/BZ.png
Executable file
After Width: | Height: | Size: 4.9 KiB |
BIN
static/countryflags/CA.png
Executable file
After Width: | Height: | Size: 1.3 KiB |
BIN
static/countryflags/CC.png
Executable file
After Width: | Height: | Size: 1.8 KiB |
BIN
static/countryflags/CD.png
Executable file
After Width: | Height: | Size: 2.6 KiB |
BIN
static/countryflags/CF.png
Executable file
After Width: | Height: | Size: 1.0 KiB |
BIN
static/countryflags/CG.png
Executable file
After Width: | Height: | Size: 1.4 KiB |
BIN
static/countryflags/CH.png
Executable file
After Width: | Height: | Size: 827 B |
BIN
static/countryflags/CI.png
Executable file
After Width: | Height: | Size: 669 B |
BIN
static/countryflags/CK.png
Executable file
After Width: | Height: | Size: 3.1 KiB |
BIN
static/countryflags/CL.png
Executable file
After Width: | Height: | Size: 914 B |
BIN
static/countryflags/CM.png
Executable file
After Width: | Height: | Size: 1.0 KiB |
BIN
static/countryflags/CN.png
Executable file
After Width: | Height: | Size: 1.2 KiB |
BIN
static/countryflags/CO.png
Executable file
After Width: | Height: | Size: 698 B |
BIN
static/countryflags/CR.png
Executable file
After Width: | Height: | Size: 1.4 KiB |
BIN
static/countryflags/CU.png
Executable file
After Width: | Height: | Size: 1.4 KiB |
BIN
static/countryflags/CV.png
Executable file
After Width: | Height: | Size: 1.5 KiB |
BIN
static/countryflags/CW.png
Executable file
After Width: | Height: | Size: 1007 B |
BIN
static/countryflags/CX.png
Executable file
After Width: | Height: | Size: 2.4 KiB |
BIN
static/countryflags/CY.png
Executable file
After Width: | Height: | Size: 1.7 KiB |
BIN
static/countryflags/CZ.png
Executable file
After Width: | Height: | Size: 890 B |
BIN
static/countryflags/DE.png
Executable file
After Width: | Height: | Size: 561 B |
BIN
static/countryflags/DJ.png
Executable file
After Width: | Height: | Size: 1.6 KiB |
BIN
static/countryflags/DK.png
Executable file
After Width: | Height: | Size: 803 B |
BIN
static/countryflags/DM.png
Executable file
After Width: | Height: | Size: 2.1 KiB |
BIN
static/countryflags/DO.png
Executable file
After Width: | Height: | Size: 1.5 KiB |
BIN
static/countryflags/DZ.png
Executable file
After Width: | Height: | Size: 1.5 KiB |
BIN
static/countryflags/EC.png
Executable file
After Width: | Height: | Size: 2.4 KiB |
BIN
static/countryflags/EE.png
Executable file
After Width: | Height: | Size: 559 B |
BIN
static/countryflags/EG.png
Executable file
After Width: | Height: | Size: 1.3 KiB |
BIN
static/countryflags/EH.png
Executable file
After Width: | Height: | Size: 1.3 KiB |
BIN
static/countryflags/ER.png
Executable file
After Width: | Height: | Size: 3.1 KiB |
BIN
static/countryflags/ES.png
Executable file
After Width: | Height: | Size: 2.0 KiB |
BIN
static/countryflags/ET.png
Executable file
After Width: | Height: | Size: 2.4 KiB |
BIN
static/countryflags/FI.png
Executable file
After Width: | Height: | Size: 765 B |
BIN
static/countryflags/FJ.png
Executable file
After Width: | Height: | Size: 3.0 KiB |
BIN
static/countryflags/FK.png
Executable file
After Width: | Height: | Size: 3.8 KiB |
BIN
static/countryflags/FM.png
Executable file
After Width: | Height: | Size: 1.3 KiB |
BIN
static/countryflags/FO.png
Executable file
After Width: | Height: | Size: 918 B |
BIN
static/countryflags/FR.png
Executable file
After Width: | Height: | Size: 664 B |
BIN
static/countryflags/GA.png
Executable file
After Width: | Height: | Size: 724 B |
BIN
static/countryflags/GB.png
Executable file
After Width: | Height: | Size: 2.6 KiB |
BIN
static/countryflags/GD.png
Executable file
After Width: | Height: | Size: 2.5 KiB |
BIN
static/countryflags/GE.png
Executable file
After Width: | Height: | Size: 1.4 KiB |
BIN
static/countryflags/GF.png
Executable file
After Width: | Height: | Size: 1.5 KiB |
BIN
static/countryflags/GG.png
Executable file
After Width: | Height: | Size: 1.0 KiB |
BIN
static/countryflags/GH.png
Executable file
After Width: | Height: | Size: 1.0 KiB |
BIN
static/countryflags/GI.png
Executable file
After Width: | Height: | Size: 2.3 KiB |
BIN
static/countryflags/GL.png
Executable file
After Width: | Height: | Size: 1.7 KiB |
BIN
static/countryflags/GM.png
Executable file
After Width: | Height: | Size: 720 B |
BIN
static/countryflags/GN.png
Executable file
After Width: | Height: | Size: 649 B |
BIN
static/countryflags/GP.png
Executable file
After Width: | Height: | Size: 1.0 KiB |
BIN
static/countryflags/GQ.png
Executable file
After Width: | Height: | Size: 1.5 KiB |
BIN
static/countryflags/GR.png
Executable file
After Width: | Height: | Size: 921 B |
BIN
static/countryflags/GS.png
Executable file
After Width: | Height: | Size: 4.5 KiB |
BIN
static/countryflags/GT.png
Executable file
After Width: | Height: | Size: 1.8 KiB |
BIN
static/countryflags/GU.png
Executable file
After Width: | Height: | Size: 2.1 KiB |
BIN
static/countryflags/GW.png
Executable file
After Width: | Height: | Size: 1.0 KiB |
BIN
static/countryflags/GY.png
Executable file
After Width: | Height: | Size: 2.7 KiB |
BIN
static/countryflags/HK.png
Executable file
After Width: | Height: | Size: 1.9 KiB |
BIN
static/countryflags/HN.png
Executable file
After Width: | Height: | Size: 1.1 KiB |
BIN
static/countryflags/HR.png
Executable file
After Width: | Height: | Size: 2.2 KiB |
BIN
static/countryflags/HT.png
Executable file
After Width: | Height: | Size: 1.4 KiB |