Started working on functions for the UI
This commit is contained in:
parent
5319966d7f
commit
2aaa108521
|
@ -1,5 +1,6 @@
|
||||||
import { Router } from 'express'
|
import { Router } from 'express'
|
||||||
import { sqlite } from '../libs/database/init.js'
|
import { sqlite } from '../libs/database/init.js'
|
||||||
|
import wrapper from '../libs/database/wrapper.js'
|
||||||
|
|
||||||
const finishApi = Router()
|
const finishApi = Router()
|
||||||
|
|
||||||
|
@ -16,4 +17,43 @@ finishApi.get(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
finishApi.get(
|
||||||
|
'/finishedMaps/:player',
|
||||||
|
(req, res) => {
|
||||||
|
/* Check if player exists */
|
||||||
|
if(!wrapper.playerExists(req.params.player)) {
|
||||||
|
return res.json({
|
||||||
|
success: false,
|
||||||
|
response: "No such player!"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const finishes = wrapper.finishedMaps(req.params.player)
|
||||||
|
|
||||||
|
return res.json({
|
||||||
|
success: true,
|
||||||
|
response: finishes,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
finishApi.get(
|
||||||
|
'/unfinishedMaps/:player',
|
||||||
|
(req, res) => {
|
||||||
|
/* Check if player exists */
|
||||||
|
if(!wrapper.playerExists(req.params.player)) {
|
||||||
|
return res.json({
|
||||||
|
success: false,
|
||||||
|
response: "No such player!"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const finishes = wrapper.unfinishedMaps(req.params.player)
|
||||||
|
|
||||||
|
return res.json({
|
||||||
|
success: true,
|
||||||
|
response: finishes,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
export default finishApi
|
export default finishApi
|
74
api/maps.js
74
api/maps.js
|
@ -1,5 +1,6 @@
|
||||||
import { Router } from 'express'
|
import { Router } from 'express'
|
||||||
import { sqlite } from '../libs/database/init.js'
|
import { sqlite } from '../libs/database/init.js'
|
||||||
|
import wrapper, { map } from '../libs/database/wrapper.js'
|
||||||
|
|
||||||
const mapApi = Router()
|
const mapApi = Router()
|
||||||
|
|
||||||
|
@ -18,37 +19,17 @@ mapApi.get(
|
||||||
mapApi.get(
|
mapApi.get(
|
||||||
'/get/:map',
|
'/get/:map',
|
||||||
(req, res) => {
|
(req, res) => {
|
||||||
let map = req.params.map
|
|
||||||
|
|
||||||
/* Check if map exists */
|
/* Check if map exists */
|
||||||
const check = sqlite.prepare(`SELECT map FROM maps WHERE map = ?`).get(map)
|
if(!wrapper.mapExists(req.params.map)) {
|
||||||
if (!check) {
|
|
||||||
return res.json({
|
return res.json({
|
||||||
success: false,
|
success: false,
|
||||||
response: "No map found!",
|
response: "No such map!"
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const info = sqlite.prepare(`SELECT * FROM maps WHERE map = ?`).get(map)
|
|
||||||
|
|
||||||
/* TODO: Generate a table with this as a cache */
|
|
||||||
const avgTime = sqlite.prepare(`SELECT avg(time) AS 'averageTime' FROM race WHERE map = ?`).get(map)
|
|
||||||
const total = sqlite.prepare(`SELECT COUNT(*) AS 'total' FROM race WHERE map = ?`).get(map)
|
|
||||||
const unique = sqlite.prepare(`SELECT COUNT(distinct(player)) AS 'unique' FROM race WHERE map = ?`).get(map)
|
|
||||||
const teams = sqlite.prepare(`SELECT COUNT(distinct(id)) AS 'teams' FROM teamrace WHERE map = ?`).get(map)
|
|
||||||
|
|
||||||
return res.json({
|
return res.json({
|
||||||
success: true,
|
success: true,
|
||||||
response: {
|
response: map(req.params.map)
|
||||||
info,
|
|
||||||
|
|
||||||
/* TODO Get median time*/
|
|
||||||
averageTime: avgTime.averageTime,
|
|
||||||
finishes: {
|
|
||||||
unique: unique.unique,
|
|
||||||
total: total.total,
|
|
||||||
teams: teams.teams,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -56,11 +37,9 @@ mapApi.get(
|
||||||
mapApi.get(
|
mapApi.get(
|
||||||
'/getAll',
|
'/getAll',
|
||||||
(req, res) => {
|
(req, res) => {
|
||||||
const allMaps = sqlite.prepare(`SELECT * FROM maps`).all()
|
|
||||||
|
|
||||||
return res.json({
|
return res.json({
|
||||||
success: true,
|
success: true,
|
||||||
response: allMaps,
|
response: wrapper.allMaps()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -68,22 +47,53 @@ mapApi.get(
|
||||||
mapApi.get(
|
mapApi.get(
|
||||||
'/category/:category',
|
'/category/:category',
|
||||||
(req, res) => {
|
(req, res) => {
|
||||||
let category = req.params.category
|
|
||||||
|
|
||||||
/* Check if category exists */
|
/* Check if category exists */
|
||||||
const check = sqlite.prepare(`SELECT category FROM maps WHERE category = ? LIMIT 1`).get(category)
|
if (!wrapper.categoryExists(req.params.category)) {
|
||||||
if (!check) {
|
|
||||||
return res.json({
|
return res.json({
|
||||||
success: false,
|
success: false,
|
||||||
response: "Invalid category name!",
|
response: "Invalid category name!",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const allMaps = sqlite.prepare(`SELECT * FROM maps WHERE category = ?`).all(category)
|
return res.json({
|
||||||
|
success: true,
|
||||||
|
response: wrapper.mapCategory(req.params.category)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
mapApi.get(
|
||||||
|
'/leaderboard/race/:map',
|
||||||
|
(req, res) => {
|
||||||
|
/* Check if map exists */
|
||||||
|
if (!wrapper.mapExists(req.params.map)) {
|
||||||
|
return res.json({
|
||||||
|
success: false,
|
||||||
|
response: "No such map!",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return res.json({
|
return res.json({
|
||||||
success: true,
|
success: true,
|
||||||
response: allMaps,
|
response: wrapper.leaderboardRace(req.params.map, 1, 20)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
mapApi.get(
|
||||||
|
'/leaderboard/teamrace/:map',
|
||||||
|
(req, res) => {
|
||||||
|
/* Check if map exists */
|
||||||
|
if (!wrapper.mapExists(req.params.map)) {
|
||||||
|
return res.json({
|
||||||
|
success: false,
|
||||||
|
response: "No such map!",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.json({
|
||||||
|
success: true,
|
||||||
|
response: wrapper.leaderboardTeamrace(req.params.map, 1, 20)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,32 +1,24 @@
|
||||||
import { Router } from 'express'
|
import { Router } from 'express'
|
||||||
import { sqlite } from '../libs/database/init.js'
|
import wrapper from '../libs/database/wrapper.js'
|
||||||
import searcher from '../libs/database/searcher.js'
|
|
||||||
|
|
||||||
const playerApi = Router()
|
const playerApi = Router()
|
||||||
|
|
||||||
|
|
||||||
playerApi.get(
|
playerApi.get(
|
||||||
'/get/:player',
|
'/get/:player',
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
searcher(
|
/* Check if player exists */
|
||||||
'points',
|
if(!wrapper.playerExists(req.params.player)) {
|
||||||
'player',
|
return res.json({
|
||||||
req.params.player,
|
|
||||||
undefined,
|
|
||||||
false,
|
|
||||||
"get",
|
|
||||||
0
|
|
||||||
).then(
|
|
||||||
player => res.json({
|
|
||||||
success: true,
|
|
||||||
response: player
|
|
||||||
})
|
|
||||||
).catch(
|
|
||||||
error => res.json({
|
|
||||||
success: false,
|
success: false,
|
||||||
response: error
|
response: "No such player!"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const data = wrapper.player(req.params.player)
|
||||||
|
|
||||||
|
return res.json({
|
||||||
|
success: true,
|
||||||
|
response: data
|
||||||
})
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
2
index.js
2
index.js
|
@ -4,7 +4,7 @@ import api from './api/api.js'
|
||||||
import { generateDB } from './libs/database/generate.js'
|
import { generateDB } from './libs/database/generate.js'
|
||||||
import { dbInit } from './libs/database/init.js'
|
import { dbInit } from './libs/database/init.js'
|
||||||
import { downloadEssentialData } from './libs/download/dowload.js'
|
import { downloadEssentialData } from './libs/download/dowload.js'
|
||||||
|
import tasks from './libs/database/tasks.js'
|
||||||
|
|
||||||
loadEnv()
|
loadEnv()
|
||||||
|
|
||||||
|
|
|
@ -43,11 +43,6 @@ export function generateDB() {
|
||||||
`ALTER TABLE maps RENAME COLUMN Timestamp TO release`
|
`ALTER TABLE maps RENAME COLUMN Timestamp TO release`
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
log("Generating map index...")
|
|
||||||
execMany([
|
|
||||||
`CREATE INDEX IF NOT EXISTS "idx_maps_map" ON "maps" ("map")`,
|
|
||||||
`CREATE INDEX IF NOT EXISTS "idx_maps_category" ON "maps" ("category")`
|
|
||||||
])
|
|
||||||
|
|
||||||
log("Generating race index...")
|
log("Generating race index...")
|
||||||
execMany([
|
execMany([
|
||||||
|
@ -62,12 +57,15 @@ export function generateDB() {
|
||||||
log("Creating rankings table...")
|
log("Creating rankings table...")
|
||||||
sqlite.exec(`
|
sqlite.exec(`
|
||||||
CREATE TABLE IF NOT EXISTS "rankings" (
|
CREATE TABLE IF NOT EXISTS "rankings" (
|
||||||
|
"category" varchar(32) NOT NULL,
|
||||||
|
"points" integer NOT NULL DEFAULT 0,
|
||||||
"map" varchar(128) NOT NULL,
|
"map" varchar(128) NOT NULL,
|
||||||
"player" varchar(16) NOT NULL,
|
"player" varchar(16) NOT NULL,
|
||||||
"time" float NOT NULL DEFAULT 0,
|
"time" float NOT NULL DEFAULT 0,
|
||||||
"date" timestamp NOT NULL DEFAULT current_timestamp,
|
"date" timestamp NOT NULL DEFAULT current_timestamp,
|
||||||
"server" char(4) NOT NULL DEFAULT '',
|
"server" char(4) NOT NULL DEFAULT '',
|
||||||
"rank" INTEGER NOT NULL
|
"rank" INTEGER NOT NULL,
|
||||||
|
"finishes" INTEGER NOT NULL DEFAULT 0
|
||||||
)
|
)
|
||||||
`)
|
`)
|
||||||
|
|
||||||
|
@ -78,7 +76,9 @@ export function generateDB() {
|
||||||
execMany([
|
execMany([
|
||||||
`CREATE INDEX IF NOT EXISTS "idx_rankings_map" ON "rankings" ("map")`,
|
`CREATE INDEX IF NOT EXISTS "idx_rankings_map" ON "rankings" ("map")`,
|
||||||
`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_mapRank" ON "rankings" ("map", "rank")`
|
||||||
])
|
])
|
||||||
|
|
||||||
log("Generating teamrace index...")
|
log("Generating teamrace index...")
|
||||||
|
@ -91,6 +91,8 @@ export function generateDB() {
|
||||||
log("Creating teamrankings table...")
|
log("Creating teamrankings table...")
|
||||||
sqlite.exec(`
|
sqlite.exec(`
|
||||||
CREATE TABLE IF NOT EXISTS "teamrankings" (
|
CREATE TABLE IF NOT EXISTS "teamrankings" (
|
||||||
|
"category" varchar(32) NOT NULL,
|
||||||
|
"points" integer NOT NULL DEFAULT 0,
|
||||||
"map" varchar(128) NOT NULL,
|
"map" varchar(128) NOT NULL,
|
||||||
"id" varbinary(16) NOT NULL,
|
"id" varbinary(16) NOT NULL,
|
||||||
"player" varchar(16) NOT NULL,
|
"player" varchar(16) NOT NULL,
|
||||||
|
@ -108,7 +110,9 @@ export function generateDB() {
|
||||||
execMany([
|
execMany([
|
||||||
`CREATE INDEX IF NOT EXISTS "idx_teamrankings_map" ON "teamrankings" ("map")`,
|
`CREATE INDEX IF NOT EXISTS "idx_teamrankings_map" ON "teamrankings" ("map")`,
|
||||||
`CREATE INDEX IF NOT EXISTS "idx_teamrankings_rank" ON "teamrankings" ("teamrank")`,
|
`CREATE INDEX IF NOT EXISTS "idx_teamrankings_rank" ON "teamrankings" ("teamrank")`,
|
||||||
`CREATE INDEX IF NOT EXISTS "idx_teamrankings_player" ON "teamrankings" ("player")`
|
`CREATE INDEX IF NOT EXISTS "idx_teamrankings_player" ON "teamrankings" ("player")`,
|
||||||
|
`CREATE INDEX IF NOT EXISTS "idx_teamrankings_playerCategoryMap" ON "teamrankings" ("player", "category", "map")`,
|
||||||
|
`CREATE INDEX IF NOT EXISTS "idx_teamrankings_mapTeamrank" ON "teamrankings" ("map", "teamrank")`
|
||||||
])
|
])
|
||||||
|
|
||||||
log("Generating graphRecordCache...")
|
log("Generating graphRecordCache...")
|
||||||
|
@ -131,6 +135,38 @@ export function generateDB() {
|
||||||
log("Inserting points to DB...")
|
log("Inserting points to DB...")
|
||||||
tasks.processAllPoints()
|
tasks.processAllPoints()
|
||||||
|
|
||||||
|
log("Generating a new maps table...")
|
||||||
|
/* Rename the old one as we wanna use that name for the new one*/
|
||||||
|
sqlite.exec(`ALTER TABLE maps RENAME TO oldmaps`)
|
||||||
|
|
||||||
|
sqlite.exec(`
|
||||||
|
CREATE TABLE IF NOT EXISTS "maps" (
|
||||||
|
"map" varchar(128) NOT NULL,
|
||||||
|
"category" varchar(32) NOT NULL,
|
||||||
|
"points" integer NOT NULL DEFAULT 0,
|
||||||
|
"stars" integer NOT NULL DEFAULT 0,
|
||||||
|
"mapper" char(128) NOT NULL,
|
||||||
|
"release" timestamp NOT NULL DEFAULT current_timestamp,
|
||||||
|
|
||||||
|
"avgTime" FLOAT NOT NULL DEFAULT 0,
|
||||||
|
"medianTime" FLOAT NOT NULL DEFAULT 0,
|
||||||
|
"topTime" FLOAT NOT NULL DEFAULT 0,
|
||||||
|
"topTeamTime" FLOAT NOT NULL DEFAULT 0,
|
||||||
|
"finishesUnique" INTEGER NOT NULL DEFAULT 0,
|
||||||
|
"finishesTotal" INTEGER NOT NULL DEFAULT 0,
|
||||||
|
"finishesTeam" INTEGER NOT NULL DEFAULT 0
|
||||||
|
)
|
||||||
|
`)
|
||||||
|
tasks.processMaps()
|
||||||
|
|
||||||
|
log("Generating map index...")
|
||||||
|
execMany([
|
||||||
|
`CREATE INDEX IF NOT EXISTS "idx_maps_map" ON "maps" ("map")`,
|
||||||
|
`CREATE INDEX IF NOT EXISTS "idx_maps_category" ON "maps" ("category")`
|
||||||
|
`CREATE INDEX IF NOT EXISTS "idx_maps_categoryMap" ON "maps" ("category", "map")`
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
skinDB.exec(`
|
skinDB.exec(`
|
||||||
CREATE TABLE IF NOT EXISTS "skindata" (
|
CREATE TABLE IF NOT EXISTS "skindata" (
|
||||||
"timestamp" INTEGER NOT NULL,
|
"timestamp" INTEGER NOT NULL,
|
||||||
|
|
|
@ -24,6 +24,9 @@ export function dbInit() {
|
||||||
/* Unsafe mode */
|
/* Unsafe mode */
|
||||||
sqlite.unsafeMode()
|
sqlite.unsafeMode()
|
||||||
|
|
||||||
|
/* Load external extensions */
|
||||||
|
sqlite.loadExtension('./math-func.so')
|
||||||
|
|
||||||
log("Loaded in 'ddnet.sqlite'!")
|
log("Loaded in 'ddnet.sqlite'!")
|
||||||
log("Loaded in 'skindata.sqlite'!")
|
log("Loaded in 'skindata.sqlite'!")
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,26 +7,28 @@ import { sqlite } from './init.js'
|
||||||
* @module libs/database/processRankings
|
* @module libs/database/processRankings
|
||||||
*/
|
*/
|
||||||
export function processRankings() {
|
export function processRankings() {
|
||||||
const maps = sqlite.prepare(`SELECT map FROM maps`)
|
const maps = sqlite.prepare(`SELECT * FROM maps`)
|
||||||
|
|
||||||
for (const map of maps.iterate())
|
for (const map of maps.iterate())
|
||||||
sqlite
|
sqlite
|
||||||
.prepare(`
|
.prepare(`
|
||||||
INSERT INTO rankings
|
INSERT INTO rankings
|
||||||
(
|
(
|
||||||
map, player, time, date, rank, server
|
map, category, points, player, time, date, rank, server, finishes
|
||||||
)
|
)
|
||||||
SELECT map, player, time, date, rank, server
|
SELECT a.map, b.category, b.points, a.player, a.time, a.date, a.rank, a.server, a.finishes
|
||||||
FROM (
|
FROM (
|
||||||
SELECT rank() OVER w AS rank,
|
SELECT rank() OVER w AS rank,
|
||||||
map,
|
map,
|
||||||
date,
|
date,
|
||||||
player,
|
player,
|
||||||
min(time) AS time,
|
min(time) AS time,
|
||||||
server
|
server,
|
||||||
FROM race
|
COUNT(*) AS finishes
|
||||||
|
FROM race as a
|
||||||
WHERE map = ?
|
WHERE map = ?
|
||||||
GROUP BY player window w AS (ORDER BY time) ) AS a
|
GROUP BY player window w AS (ORDER BY time) ) AS a
|
||||||
|
JOIN maps as b ON a.map = b.map
|
||||||
ORDER BY rank
|
ORDER BY rank
|
||||||
`)
|
`)
|
||||||
.run(map.map)
|
.run(map.map)
|
||||||
|
@ -44,12 +46,13 @@ export function processTeamRankings() {
|
||||||
.prepare(`
|
.prepare(`
|
||||||
INSERT INTO teamrankings
|
INSERT INTO teamrankings
|
||||||
(
|
(
|
||||||
player, map, id, time, date, server, teamrank
|
player, map, id, time, date, server, teamrank, category, points
|
||||||
)
|
)
|
||||||
SELECT DISTINCT(r.player),
|
SELECT DISTINCT(r.player),
|
||||||
r.map, r.id, r.time, r.date,
|
r.map, r.id, r.time, r.date,
|
||||||
Substring(n.server, 1, 3),
|
Substring(n.server, 1, 3),
|
||||||
dense_rank() OVER w AS rank
|
dense_rank() OVER w AS rank,
|
||||||
|
a.category, a.points
|
||||||
FROM ((
|
FROM ((
|
||||||
SELECT DISTINCT id
|
SELECT DISTINCT id
|
||||||
FROM teamrace
|
FROM teamrace
|
||||||
|
@ -61,7 +64,9 @@ export function processTeamRankings() {
|
||||||
INNER JOIN race AS n
|
INNER JOIN race AS n
|
||||||
ON r.map = n.map
|
ON r.map = n.map
|
||||||
AND r.player = n.player
|
AND r.player = n.player
|
||||||
AND r.time = n.time window w AS (ORDER BY r.time)
|
AND r.time = n.time
|
||||||
|
JOIN maps as a
|
||||||
|
ON r.map = a.map window w AS (ORDER BY r.time)
|
||||||
`)
|
`)
|
||||||
.run(map.map)
|
.run(map.map)
|
||||||
}
|
}
|
||||||
|
@ -99,6 +104,45 @@ export function processTimeGraph() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This generates a fancy map table containing more data such total finishes, median time.
|
||||||
|
* @module libs/database/processMaps
|
||||||
|
*/
|
||||||
|
export function processMaps() {
|
||||||
|
const maps = sqlite.prepare(`SELECT map FROM oldmaps`)
|
||||||
|
const finishes = sqlite.prepare(`SELECT * FROM race WHERE map = ? ORDER BY date`)
|
||||||
|
|
||||||
|
for (const map of maps.iterate()) {
|
||||||
|
const info = sqlite.prepare(`SELECT * FROM oldmaps WHERE map = ?`).get(map.map)
|
||||||
|
|
||||||
|
const avgTime = sqlite.prepare(`SELECT avg(time) AS avgTime FROM race WHERE map = ?`).get(map.map)?.avgTime ?? -1
|
||||||
|
const medianTime = sqlite.prepare(`SELECT median(time) as medianTime FROM race WHERE map = ?`).get(map.map)?.medianTime ?? -1
|
||||||
|
|
||||||
|
const teams = sqlite.prepare(`SELECT COUNT(distinct(id)) AS 'teams' FROM teamrace WHERE map = ?`).get(map.map)?.teams ?? -1
|
||||||
|
const topTeamTime = sqlite.prepare(`SELECT time as topTeamTime FROM teamrankings WHERE map = ? ORDER BY Time ASC LIMIT 1`).get(map.map)?.topTeamTime ?? -1
|
||||||
|
|
||||||
|
const topTime = sqlite.prepare(`SELECT time as topTime FROM rankings WHERE map = ? ORDER BY Time ASC LIMIT 1`).get(map.map)?.topTime ?? -1
|
||||||
|
|
||||||
|
|
||||||
|
const total = sqlite.prepare(`SELECT COUNT(*) AS 'total' FROM race WHERE map = ?`).get(map.map)?.total ?? -1
|
||||||
|
const unique = sqlite.prepare(`SELECT COUNT(distinct(player)) AS 'unique' FROM race WHERE map = ?`).get(map.map)?.unique ?? -1
|
||||||
|
|
||||||
|
|
||||||
|
sqlite.prepare(`
|
||||||
|
INSERT INTO "maps"
|
||||||
|
(
|
||||||
|
map, category, points, stars, mapper, release,
|
||||||
|
avgTime, medianTime, topTime, topTeamTime,
|
||||||
|
finishesUnique, finishesTotal, finishesTeam
|
||||||
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
`).run(
|
||||||
|
info.map, info.category, info.points, info.stars, info.mapper, info.release,
|
||||||
|
avgTime, medianTime, topTime, topTeamTime,
|
||||||
|
unique, total, teams,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This inserts all types of points into a table...
|
* This inserts all types of points into a table...
|
||||||
* @module db/processAllPoints
|
* @module db/processAllPoints
|
||||||
|
@ -160,5 +204,6 @@ export default {
|
||||||
processAllPoints,
|
processAllPoints,
|
||||||
processRankings,
|
processRankings,
|
||||||
processTeamRankings,
|
processTeamRankings,
|
||||||
|
processMaps,
|
||||||
processTimeGraph
|
processTimeGraph
|
||||||
}
|
}
|
335
libs/database/wrapper.js
Normal file
335
libs/database/wrapper.js
Normal file
|
@ -0,0 +1,335 @@
|
||||||
|
import { sqlite } from './init.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function checks if a player exists
|
||||||
|
*
|
||||||
|
* @param {string} player The player to check
|
||||||
|
|
||||||
|
* @returns {boolean} Returns a boolean
|
||||||
|
*/
|
||||||
|
export function playerExists(player) {
|
||||||
|
const exists = sqlite.prepare(`SELECT * FROM points WHERE player = ? LIMIT 1`).get(player)
|
||||||
|
|
||||||
|
if(exists)
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function checks if a map exists
|
||||||
|
*
|
||||||
|
* @param {string} player The map to check
|
||||||
|
|
||||||
|
* @returns {boolean} Returns a boolean
|
||||||
|
*/
|
||||||
|
export function mapExists(map) {
|
||||||
|
const exists = sqlite.prepare(`SELECT * FROM maps WHERE map = ? LIMIT 1`).get(map)
|
||||||
|
|
||||||
|
if(exists)
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function checks if a map category exists
|
||||||
|
*
|
||||||
|
* @param {string} player The category to check
|
||||||
|
|
||||||
|
* @returns {boolean} Returns a boolean
|
||||||
|
*/
|
||||||
|
export function categoryExists(category) {
|
||||||
|
const exists = sqlite.prepare(`SELECT category FROM maps WHERE category = ? LIMIT 1`).get(category)
|
||||||
|
|
||||||
|
if(exists)
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns all data pertaining a certain player
|
||||||
|
*
|
||||||
|
* @param {string} player The player to fetch
|
||||||
|
|
||||||
|
* @returns {object} An object containing the players data
|
||||||
|
*/
|
||||||
|
export function player(player) {
|
||||||
|
/* Misc */
|
||||||
|
const firstFinish = sqlite.prepare(`SELECT map, time, date, server FROM race WHERE player = ? ORDER BY date ASC LIMIT 1`).get(player)
|
||||||
|
|
||||||
|
/* Points */
|
||||||
|
let points = {}
|
||||||
|
let rank = {}
|
||||||
|
|
||||||
|
const pointsData = sqlite.prepare(`SELECT * FROM points WHERE player = ?`)
|
||||||
|
|
||||||
|
for (const pointsType of pointsData.iterate(player)) {
|
||||||
|
rank[pointsType.type] = pointsType.rank
|
||||||
|
}
|
||||||
|
for (const pointsType of pointsData.iterate(player)) {
|
||||||
|
points[pointsType.type] = pointsType.points
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
player,
|
||||||
|
firstFinish,
|
||||||
|
points,
|
||||||
|
rank,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns all data pertaining a certain map
|
||||||
|
*
|
||||||
|
* @param {string} map The map to fetch
|
||||||
|
|
||||||
|
* @returns {object} An object containing map data
|
||||||
|
*/
|
||||||
|
export function map(map) {
|
||||||
|
const a = sqlite.prepare(`
|
||||||
|
SELECT * FROM maps WHERE map = ?
|
||||||
|
`).get(map)
|
||||||
|
|
||||||
|
return prettyifyMap(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mapCategory(category) {
|
||||||
|
let output = []
|
||||||
|
const maps = sqlite.prepare(`
|
||||||
|
SELECT * FROM maps WHERE category = ?`).all(category)
|
||||||
|
|
||||||
|
for(const map of maps) {
|
||||||
|
output.push(prettyifyMap(map))
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns all data pertaining to all maps
|
||||||
|
|
||||||
|
* @returns {array} An array contaning all map objects
|
||||||
|
*/
|
||||||
|
export function allMaps() {
|
||||||
|
let output = []
|
||||||
|
const maps = sqlite.prepare(`
|
||||||
|
SELECT * FROM maps`).all()
|
||||||
|
|
||||||
|
for(const map of maps) {
|
||||||
|
output.push(prettyifyMap(map))
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns all data pertaining a certain map
|
||||||
|
*
|
||||||
|
* @param {string} map The map to fetch
|
||||||
|
|
||||||
|
* @returns {object} An object containing map data
|
||||||
|
*/
|
||||||
|
export function prettyifyMap(a) {
|
||||||
|
let output
|
||||||
|
|
||||||
|
output = {
|
||||||
|
map: a.map,
|
||||||
|
category: a.category,
|
||||||
|
points: a.points,
|
||||||
|
stars: a.stars,
|
||||||
|
release: a.release,
|
||||||
|
mappers: a.mapper.split(" & "),
|
||||||
|
|
||||||
|
times: {
|
||||||
|
average: a.avgTime,
|
||||||
|
median: a.medianTime,
|
||||||
|
topTime: a.topTime,
|
||||||
|
topTimeTeam: (a.topTeamTime != -1) ? a.topTeamTime : undefined,
|
||||||
|
},
|
||||||
|
finishes: {
|
||||||
|
total: a.finishesTotal,
|
||||||
|
team: a.finishesTeam,
|
||||||
|
unique: a.finishesUnique,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns the race leaderboard for a map
|
||||||
|
*
|
||||||
|
* @param {string} map The map to check
|
||||||
|
* @param {number} start At which rank the leaderboard should begin
|
||||||
|
* @param {number} end At which rank the leaderboard should end
|
||||||
|
|
||||||
|
* @returns {array} An array containing the leaderboard
|
||||||
|
*/
|
||||||
|
export function leaderboardRace(map, start, end) {
|
||||||
|
const leaderboard = sqlite.prepare(`
|
||||||
|
SELECT rank, time, date, player, server FROM rankings WHERE map = ? AND rank >= ? AND rank <= ?`)
|
||||||
|
.all(map, start, end)
|
||||||
|
|
||||||
|
return leaderboard
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns the teamrace leaderboard for a map
|
||||||
|
*
|
||||||
|
* @param {string} map The map to check
|
||||||
|
* @param {number} start At which rank the leaderboard should begin
|
||||||
|
* @param {number} end At which rank the leaderboard should end
|
||||||
|
|
||||||
|
* @returns {array} An array containing the leaderboard
|
||||||
|
*/
|
||||||
|
export function leaderboardTeamrace(map, start, end) {
|
||||||
|
// TODO: Optimize array creation of players
|
||||||
|
let leaderboard = []
|
||||||
|
|
||||||
|
const a = sqlite.prepare(`
|
||||||
|
SELECT teamrank, time, date, player, server FROM teamrankings WHERE map = ? AND teamrank >= ? AND teamrank <= ? GROUP BY teamrank`)
|
||||||
|
|
||||||
|
for(const teamrank of a.iterate(map, start, end)) {
|
||||||
|
let players = []
|
||||||
|
const b = sqlite.prepare(`SELECT player FROM teamrankings WHERE map = ? AND teamrank = ?`)
|
||||||
|
|
||||||
|
for(const player of b.iterate(map, teamrank.teamrank)) {
|
||||||
|
players.push(player.player)
|
||||||
|
}
|
||||||
|
leaderboard.push({
|
||||||
|
teamrank: teamrank.teamrank,
|
||||||
|
time: teamrank.time,
|
||||||
|
date: teamrank.date,
|
||||||
|
server: teamrank.server,
|
||||||
|
players: players,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return leaderboard
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns the points leaderboard for a specific type
|
||||||
|
* (points, pointsRank, pointsTeam, pointsThisWeek, pointsThisMonth)
|
||||||
|
*
|
||||||
|
* @param {string} type Which type of points to fetch
|
||||||
|
* @param {number} start At which rank the leaderboard should begin
|
||||||
|
* @param {number} end At which rank the leaderboard should end
|
||||||
|
|
||||||
|
* @returns {array} An array containing the leaderboard
|
||||||
|
*/
|
||||||
|
export function leaderboardPoints(map, start, end) {
|
||||||
|
const leaderboard = sqlite.prepare(`
|
||||||
|
SELECT rank, player, points FROM points WHERE type = ? AND rank >= ? AND rank <= ? ORDER BY rank`)
|
||||||
|
.all(type, start, end)
|
||||||
|
|
||||||
|
return leaderboard
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns all finished maps by a specific player
|
||||||
|
* togheter with their respective rank, teamrank, amount of finishes.
|
||||||
|
* Finishes are grouped by map category (Novice, Brutal)
|
||||||
|
*
|
||||||
|
* @param {string} player The player to check
|
||||||
|
|
||||||
|
* @returns {object} An object containing all finishes grouped by category
|
||||||
|
*/
|
||||||
|
export function finishedMaps(player) {
|
||||||
|
const finishesStmt = sqlite.prepare(
|
||||||
|
`
|
||||||
|
SELECT a.map,
|
||||||
|
a.category,
|
||||||
|
a.points,
|
||||||
|
a.rank,
|
||||||
|
b.teamrank,
|
||||||
|
a.finishes
|
||||||
|
FROM rankings AS a
|
||||||
|
LEFT OUTER JOIN teamrankings AS b
|
||||||
|
ON a.player = b.player
|
||||||
|
AND a.category = b.category
|
||||||
|
AND a.map = b.map
|
||||||
|
WHERE a.player = ?
|
||||||
|
`)
|
||||||
|
|
||||||
|
let finishes = {
|
||||||
|
Novice: [],
|
||||||
|
Moderate: [],
|
||||||
|
Brutal: [],
|
||||||
|
Insane: [],
|
||||||
|
Dummy: [],
|
||||||
|
DDmaX: [],
|
||||||
|
Oldschool: [],
|
||||||
|
Solo: [],
|
||||||
|
Race: [],
|
||||||
|
Fun: []
|
||||||
|
}
|
||||||
|
for (const finish of finishesStmt.iterate(player)) {
|
||||||
|
finishes[finish.category].push(finish)
|
||||||
|
}
|
||||||
|
|
||||||
|
return finishes
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns all unfinished maps by a specific player
|
||||||
|
* togheter with category, points, finishTotal and medianTime.
|
||||||
|
* Maps are grouped by the map category (Novice, Brutal)
|
||||||
|
*
|
||||||
|
* @param {string} player The player to check
|
||||||
|
|
||||||
|
* @returns {object} An object containing all unfinished maps
|
||||||
|
*/
|
||||||
|
export function unfinishedMaps(player) {
|
||||||
|
const maps = sqlite.prepare(
|
||||||
|
`
|
||||||
|
SELECT a.map,
|
||||||
|
a.category,
|
||||||
|
a.points,
|
||||||
|
b.finishesTotal,
|
||||||
|
b.medianTime
|
||||||
|
FROM (SELECT category,
|
||||||
|
map,
|
||||||
|
points
|
||||||
|
FROM maps
|
||||||
|
WHERE map NOT IN (SELECT map
|
||||||
|
FROM rankings
|
||||||
|
WHERE player = ? )) AS a
|
||||||
|
JOIN maps AS b
|
||||||
|
ON a.category = b.category
|
||||||
|
AND a.map = b.map
|
||||||
|
ORDER BY b.category ASC;
|
||||||
|
`)
|
||||||
|
|
||||||
|
let unfinished = {
|
||||||
|
Novice: [],
|
||||||
|
Moderate: [],
|
||||||
|
Brutal: [],
|
||||||
|
Insane: [],
|
||||||
|
Dummy: [],
|
||||||
|
DDmaX: [],
|
||||||
|
Oldschool: [],
|
||||||
|
Solo: [],
|
||||||
|
Race: [],
|
||||||
|
Fun: []
|
||||||
|
}
|
||||||
|
for (const map of maps.iterate(player)) {
|
||||||
|
unfinished[map.category].push(map)
|
||||||
|
}
|
||||||
|
|
||||||
|
return unfinished
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
playerExists,
|
||||||
|
finishedMaps,
|
||||||
|
unfinishedMaps,
|
||||||
|
player,
|
||||||
|
|
||||||
|
map,
|
||||||
|
mapCategory,
|
||||||
|
allMaps,
|
||||||
|
mapExists,
|
||||||
|
leaderboardRace,
|
||||||
|
leaderboardTeamrace,
|
||||||
|
categoryExists,
|
||||||
|
}
|
BIN
math-func.so
Executable file
BIN
math-func.so
Executable file
Binary file not shown.
Loading…
Reference in New Issue
Block a user