Springcleaning
This commit is contained in:
parent
c5427e0ee3
commit
ca617d50d3
24
api/api.js
24
api/api.js
|
@ -1,24 +0,0 @@
|
|||
import { Router } from 'express'
|
||||
import finishApi from './finishes.js'
|
||||
import mapApi from './maps.js'
|
||||
import playerApi from './players.js'
|
||||
|
||||
const api = Router()
|
||||
|
||||
api.get(
|
||||
'/',
|
||||
(req, res) => res.json({
|
||||
success: true,
|
||||
response: "You connected to DDStats API! :D"
|
||||
})
|
||||
)
|
||||
|
||||
api.use('/finishes', finishApi)
|
||||
api.use('/maps', mapApi)
|
||||
api.use('/players', playerApi)
|
||||
|
||||
/**
|
||||
* This module is the entrypoint for the API.
|
||||
* @module api/api
|
||||
*/
|
||||
export default api
|
|
@ -1,57 +0,0 @@
|
|||
import { Router } from 'express'
|
||||
import Finish from '../schemas/Finish.js'
|
||||
|
||||
const finishApi = Router()
|
||||
|
||||
finishApi.get(
|
||||
'/count',
|
||||
(req, res) => {
|
||||
Finish.find({}).count().then(
|
||||
finishAmount => {
|
||||
res.json({
|
||||
success: true,
|
||||
response: finishAmount
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
finishApi.get(
|
||||
'/find',
|
||||
async (req, res) => {
|
||||
if (!req.query.player && !req.query.map)
|
||||
return res.json({
|
||||
success: false,
|
||||
response: "Please provide either a player or map!"
|
||||
})
|
||||
|
||||
const player = req.query.player
|
||||
const map = req.query.map
|
||||
const sort = req.query.sort ?? 'date'
|
||||
const order = req.query.order === "desc" ? -1 : 1
|
||||
|
||||
Finish.find({ player: player ?? /\w/, map: map ?? /\w/ }).sort([[sort, order]]).then(
|
||||
finishes => {
|
||||
if (!finishes[0])
|
||||
return res.json({
|
||||
success: false,
|
||||
response: "No maps found!"
|
||||
})
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
response: {
|
||||
finishes
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* This module handles all API actions related to maps.
|
||||
* @module api/finishes
|
||||
*/
|
||||
export default finishApi
|
115
api/maps.js
115
api/maps.js
|
@ -1,115 +0,0 @@
|
|||
import { Router } from 'express'
|
||||
import Level from '../schemas/Level.js'
|
||||
|
||||
const mapApi = Router()
|
||||
|
||||
mapApi.get(
|
||||
'/count',
|
||||
(req, res) => {
|
||||
Level.find({}).count().then(
|
||||
mapAmount => {
|
||||
res.json({
|
||||
success: true,
|
||||
response: mapAmount
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
mapApi.get(
|
||||
'/get/:map',
|
||||
(req, res) => {
|
||||
Level.findOne({ name: req.params.map }).then(
|
||||
map => {
|
||||
if (!map)
|
||||
return res.json({
|
||||
success: false,
|
||||
response: "No map found!"
|
||||
})
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
response: map
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
mapApi.get(
|
||||
'/getAll',
|
||||
(req, res) => {
|
||||
Level.find({}).then(
|
||||
maps => {
|
||||
res.json({
|
||||
success: true,
|
||||
response: maps
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
mapApi.get(
|
||||
'/category/:category',
|
||||
(req, res) => {
|
||||
Level.find({ category: req.params.category }).then(
|
||||
maps => {
|
||||
if (!maps[0])
|
||||
return res.json({
|
||||
success: false,
|
||||
response: "Invalid category name!"
|
||||
})
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
response: maps
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
mapApi.get(
|
||||
'/search',
|
||||
async (req, res) => {
|
||||
if (!req.query.q)
|
||||
return res.json({
|
||||
success: false,
|
||||
response: "No query ('host/path?q=query') provided!"
|
||||
})
|
||||
|
||||
const name = req.query.q
|
||||
const sort = req.query.sort ?? 'name'
|
||||
const order = req.query.order === "desc" ? -1 : 1
|
||||
const page = req.query.page ?? 1
|
||||
const filter = req.query.byMapper ? { mapper: { $regex: name, $options: 'i' }} : { name: { $regex: name, $options: 'i' }}
|
||||
const pageCount = Math.ceil((await Level.find({ name: { $regex: name, $options: 'i' }}).count()) / 20)
|
||||
|
||||
Level.find(filter).sort([[sort, order]]).limit(20).skip((page - 1) * 20).then(
|
||||
maps => {
|
||||
if (!maps[0])
|
||||
return res.json({
|
||||
success: false,
|
||||
response: "No maps found!"
|
||||
})
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
response: {
|
||||
pageCount,
|
||||
maps
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* This module handles all API actions related to maps.
|
||||
* @module api/maps
|
||||
*/
|
||||
export default mapApi
|
|
@ -1,80 +0,0 @@
|
|||
import { Router } from 'express'
|
||||
import Player from '../schemas/Player.js'
|
||||
|
||||
|
||||
const playerApi = Router()
|
||||
|
||||
playerApi.get(
|
||||
'/count',
|
||||
(req, res) => {
|
||||
Player.count({}).then(
|
||||
playerAmount => {
|
||||
res.json({
|
||||
success: true,
|
||||
response: playerAmount
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
playerApi.get(
|
||||
'/get/:player',
|
||||
(req, res) => {
|
||||
Player.findOne({ name: req.params.player }).then(
|
||||
player => {
|
||||
if (!player)
|
||||
return res.json({
|
||||
success: false,
|
||||
response: "No player found!"
|
||||
})
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
response: player
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
playerApi.get(
|
||||
'/search',
|
||||
async (req, res) => {
|
||||
if (!req.query.q)
|
||||
return res.json({
|
||||
success: false,
|
||||
response: "No query ('host/path?q=query') provided!"
|
||||
})
|
||||
|
||||
const name = req.query.q
|
||||
const sort = req.query.sort ?? 'name'
|
||||
const order = req.query.order === "desc" ? -1 : 1
|
||||
const page = req.query.page ?? 1
|
||||
const pageCount = Math.ceil((await Player.find({ name: { $regex: name, $options: 'i' }}).count()) / 20)
|
||||
|
||||
Player.find({ name: { $regex: name, $options: 'i' }}).sort([[sort, order]]).limit(20).skip((page - 1) * 20).then(
|
||||
players => {
|
||||
if (!players[0])
|
||||
return res.json({
|
||||
success: false,
|
||||
response: "No players found!"
|
||||
})
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
response: {
|
||||
pageCount,
|
||||
players
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* This module handles all API actions related to players.
|
||||
* @module api/players
|
||||
*/
|
||||
export default playerApi
|
14
index.js
14
index.js
|
@ -8,11 +8,7 @@ import express from 'express'
|
|||
import dotenv from 'dotenv'
|
||||
import njk from 'nunjucks'
|
||||
|
||||
import sqlite2mongo from './libs/database/sqlite2mongo.js'
|
||||
import databaseInit from './libs/database/init.js'
|
||||
import initLog from './libs/utils/log.js'
|
||||
|
||||
import api from './api/api.js'
|
||||
import routes from './routes/routes.js'
|
||||
|
||||
import { initWorkers } from './libs/utils/multithread.js'
|
||||
|
@ -22,15 +18,6 @@ const log = initLog("[ MAIN ]")
|
|||
// Read the .env file
|
||||
dotenv.config()
|
||||
|
||||
// await databaseInit()
|
||||
|
||||
initWorkers(process.env.THREADS ?? 4)
|
||||
|
||||
if (process.env.LOAD_DB === "true")
|
||||
await sqlite2mongo()
|
||||
|
||||
|
||||
|
||||
const Server = express()
|
||||
|
||||
njk.configure(
|
||||
|
@ -45,6 +32,5 @@ njk.configure(
|
|||
|
||||
Server.use('/', routes)
|
||||
Server.use('/assets', express.static('static'))
|
||||
Server.use('/api', api)
|
||||
|
||||
Server.listen(process.env.PORT ?? 12345, () => log(`Server started and listening on port ${process.env.PORT}.`))
|
|
@ -1,22 +0,0 @@
|
|||
import initLog from '../utils/log.js'
|
||||
import { checkForFinishes, checkForMaps, checkForPlayers } from './sqlite2mongo/checks.js'
|
||||
import postTasks from './sqlite2mongo/postTasks.js'
|
||||
|
||||
const log = initLog("sqlite2mongo")
|
||||
|
||||
/**
|
||||
* This function handles the sqlite database provided by DDNet and
|
||||
* migrates the data to mongodb.
|
||||
* @module libs/database/sqlite2mongo
|
||||
*/
|
||||
async function sqlite2mongo() {
|
||||
log("Checking for additions to 'ddnet.sqlite'...")
|
||||
|
||||
await checkForMaps()
|
||||
await checkForPlayers()
|
||||
await checkForFinishes()
|
||||
|
||||
await postTasks()
|
||||
}
|
||||
|
||||
export default sqlite2mongo
|
|
@ -1,126 +0,0 @@
|
|||
import { sqlite } from "../init.js"
|
||||
import Level from '../../../schemas/Level.js'
|
||||
import Player from '../../../schemas/Player.js'
|
||||
import Finish from '../../../schemas/Finish.js'
|
||||
import initLog from '../../utils/log.js'
|
||||
|
||||
|
||||
const log = initLog("sqlite2mongo")
|
||||
|
||||
/**
|
||||
* This for new maps from the sqlite db. If any are found it adds them to mongodb.
|
||||
* @module libs/database/sqlite2mongo/checks
|
||||
*/
|
||||
export async function checkForMaps() {
|
||||
log("Checking for new maps...")
|
||||
|
||||
const latestMap = await Level.findOne({}).sort({ "release": "desc" })
|
||||
const date = latestMap ? latestMap.release.toISOString().replace(/[TZ]/g, " ").replace(/\.[0-9\s]+/, "") : undefined
|
||||
const newMapsAmount = (await sqlite.get(`SELECT count(Map) FROM maps ${date ? `WHERE Timestamp > datetime('${date}')` : ''} ORDER BY Timestamp`))['count(Map)']
|
||||
log(`Found ${newMapsAmount} new maps!`)
|
||||
|
||||
let addedMaps = 0
|
||||
await sqlite.each(
|
||||
`SELECT Map, Server, Points, Stars, Mapper, Timestamp FROM maps ${date ? `WHERE Timestamp > datetime('${date}')` : ''} ORDER BY Timestamp`,
|
||||
[],
|
||||
(err, map) => {
|
||||
if (err) return log(err)
|
||||
|
||||
Level.create({
|
||||
name: map.Map,
|
||||
mapper: map.Mapper,
|
||||
release: map.Timestamp === '0000-00-00 00:00:00' ? new Date('January 1, 1970 00:00:00 UTC') : new Date(`${map.Timestamp}+00:00`),
|
||||
category: map.Server,
|
||||
rating: map.Stars,
|
||||
awardPoints: map.Points
|
||||
}).then(() => {
|
||||
++addedMaps
|
||||
log(`Added map ${addedMaps}/${newMapsAmount} -> ${map.Map}`)
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This checks for new players in the sqlite db. If any are found it adds them to mongodb.
|
||||
* @module libs/database/sqlite2mongo/checks
|
||||
*/
|
||||
export async function checkForPlayers() {
|
||||
log("Checking for new players...")
|
||||
|
||||
const latestPlayer = await Player.findOne({}).sort({ "firstFinish": "desc" })
|
||||
const date = latestPlayer ? latestPlayer.firstFinish.toISOString().replace(/[TZ]/g, " ").replace(/\.[0-9\s]+/, "") : undefined
|
||||
const newPlayerAmount = (await sqlite.get(`select count(Name) FROM (SELECT Name, Timestamp FROM (SELECT Name, Timestamp FROM (SELECT * FROM race ORDER BY Timestamp ASC, Name ASC) GROUP BY Name) ${date ? `WHERE Timestamp > datetime('${date}')` : ''} ORDER BY Timestamp ASC)`))['count(Name)']
|
||||
if (newPlayerAmount === 0) return log("No new players found...")
|
||||
|
||||
// Create a temporary table to prevent re-running CPU-intensive queries.
|
||||
log(`Found ${newPlayerAmount} new players!`)
|
||||
log("Importing new players...")
|
||||
await sqlite.exec("DROP TABLE IF EXISTS temp")
|
||||
await sqlite.exec("CREATE TABLE temp(Name varchar(128) NOT NULL, Timestamp timestamp NOT NULL)")
|
||||
await sqlite.exec(`INSERT INTO TEMP (Name, Timestamp) SELECT Name, Timestamp FROM (SELECT Name, Timestamp FROM (SELECT Name, Timestamp FROM (SELECT * FROM race ORDER BY Timestamp ASC, Name ASC) GROUP BY Name) ${date ? `WHERE Timestamp > datetime('${date}')` : ''} ORDER BY Timestamp ASC)`)
|
||||
log("Imported new players into 'temp'!")
|
||||
|
||||
let addedPlayers = 0
|
||||
let offset = -1
|
||||
while (offset < newPlayerAmount) {
|
||||
await sqlite.each(
|
||||
`SELECT Name, Timestamp FROM temp LIMIT 10000 OFFSET ${offset + 1}`,
|
||||
[],
|
||||
async (err, player) => {
|
||||
if (err) return log(err)
|
||||
if (addedPlayers >= newPlayerAmount) return {}
|
||||
|
||||
Player.create({
|
||||
name: player.Name,
|
||||
firstFinish: player.Timestamp === '0000-00-00 00:00:00' ? new Date('January 1, 1970 00:00:00 UTC') : new Date(`${player.Timestamp}+00:00`)
|
||||
}).then(() => {
|
||||
++addedPlayers
|
||||
log(`Added player ${addedPlayers}/${newPlayerAmount} -> ${player.Name}`)
|
||||
})
|
||||
}
|
||||
)
|
||||
offset += 10000
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This checks for new finishes in the sqlite db. If any are found it adds them to mongodb.
|
||||
* @module libs/database/sqlite2mongo/checks
|
||||
*/
|
||||
export async function checkForFinishes() {
|
||||
log("Checking for new finishes...")
|
||||
|
||||
const latestFinish = await Finish.findOne({}).sort({ "date": "desc" })
|
||||
const date = latestFinish ? latestFinish.date.toISOString().replace(/[TZ]/g, " ").replace(/\.[0-9\s]+/, "") : undefined
|
||||
const newFinishAmount = (await sqlite.get(`SELECT count(Name) FROM race ${date ? `WHERE Timestamp > datetime('${date}')` : ''}`))['count(Name)']
|
||||
if (newFinishAmount === 0) return log("No new finishes found...")
|
||||
|
||||
log(`Found ${newFinishAmount} new finishes!`)
|
||||
|
||||
let addedFinishes = 0
|
||||
let offset = -1
|
||||
while (offset < newFinishAmount) {
|
||||
await sqlite.each(
|
||||
`SELECT * FROM race ${date ? `WHERE Timestamp > datetime('${date}')` : ''} ORDER BY Timestamp LIMIT 5000 OFFSET ${offset + 1}`,
|
||||
[],
|
||||
async (err, finish) => {
|
||||
if (err) return log(err)
|
||||
if (addedFinishes >= newFinishAmount) return {}
|
||||
|
||||
Finish.create({
|
||||
map: finish.Map,
|
||||
time: finish.Time,
|
||||
date: finish.Timestamp === '0000-00-00 00:00:00' ? new Date('January 1, 1970 00:00:00 UTC') : new Date(`${finish.Timestamp}+00:00`),
|
||||
serverLocation: finish.Server ?? '',
|
||||
player: finish.Name
|
||||
}).then(() => {
|
||||
++addedFinishes
|
||||
log(`Added finish ${addedFinishes}/${newFinishAmount} -> At ${finish.Timestamp} «${finish.Name}» completed «${finish.Map}» in ${finish.Time} s`)
|
||||
})
|
||||
}
|
||||
)
|
||||
offset += 5000
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
import fs from 'fs'
|
||||
import msgpack from '@msgpack/msgpack'
|
||||
|
||||
/**
|
||||
* This module parses the msgpack provided by DDNet...
|
||||
* @module libs/database/sqlite2mongo/decodeMsgpack
|
||||
*/
|
||||
export default 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
|
||||
}
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
import Level from '../../../schemas/Level.js'
|
||||
import Player from '../../../schemas/Player.js'
|
||||
import initLog from '../../utils/log.js'
|
||||
import decodeMsgpack from './decodeMsgpack.js'
|
||||
import { spread } from '../../utils/multithread.js'
|
||||
|
||||
const log = initLog("sqlite2mongo")
|
||||
|
||||
/**
|
||||
* This handles some post-tasks that run after the initial checks.
|
||||
* @module libs/database/sqlite2mongo/postTasks
|
||||
*/
|
||||
export default async function postTasks() {
|
||||
log("Post tasks...")
|
||||
|
||||
log("Loading cached info from DDNet...")
|
||||
const cache = decodeMsgpack()
|
||||
|
||||
log("Adding total amounts of finishes to maps...")
|
||||
const totalMaps = await Level.find({}).count()
|
||||
let processedMaps = 0
|
||||
for (const category in cache.maps) {
|
||||
for (const map of cache.maps[category]) {
|
||||
Level.findOneAndUpdate(
|
||||
{ name: map[0] },
|
||||
{ totalFinishes: map[2] }
|
||||
).then(
|
||||
() => {
|
||||
++processedMaps
|
||||
log(`Processed map ${processedMaps}/${totalMaps} -> «${map[0]}» [${category}] with ${map[2]} finishes!`)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
log("Reseting weekly and monthly points...")
|
||||
await Player.updateMany({}, { pointsThisWeek: 0, pointsThisMonth: 0 })
|
||||
log("Done!")
|
||||
|
||||
log("Processing points for players...")
|
||||
const totalPlayers = await Player.find({}).count()
|
||||
let processedPlayerPoints = 0
|
||||
for (const entry of cache.pointsRanks) {
|
||||
spread(
|
||||
'./playerPoints.js',
|
||||
{
|
||||
name: entry[0],
|
||||
points: entry[1]
|
||||
}
|
||||
).then(
|
||||
() => {
|
||||
++processedPlayerPoints
|
||||
log(`Processed player ${processedPlayerPoints}/${totalPlayers} -> «${entry[0]}» has ${entry[1]} points!`)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
log("Processing rank points for players...")
|
||||
let processedPlayerRankPoints = 0
|
||||
for (const entry of cache.rankPoints) {
|
||||
spread(
|
||||
'./playerRankPoints.js',
|
||||
{
|
||||
name: entry[0],
|
||||
rankPoints: entry[1]
|
||||
}
|
||||
).then(
|
||||
() => {
|
||||
++processedPlayerRankPoints
|
||||
log(`Processed player ${processedPlayerRankPoints}/${cache.rankPoints.length} -> «${entry[0]}» has ${entry[1]} rank points!`)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
log("Processing team points for players...")
|
||||
let processedTeamPoints = 0
|
||||
for (const entry in cache.teamRankPoints) {
|
||||
spread(
|
||||
'./playerTeamPoints.js',
|
||||
{
|
||||
name: entry[0],
|
||||
teamPoints: entry[1]
|
||||
}
|
||||
).then(
|
||||
() => {
|
||||
++processedTeamPoints
|
||||
log(`Processed player ${processedTeamPoints}/${cache.teamRankPoints.length} -> «${entry[0]}» has ${entry[1]} team points!`)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
log("Processing players' points for the last week...")
|
||||
let processedPlayerPointsWeek = 0
|
||||
for (const entry of cache.pointsThisWeek) {
|
||||
spread(
|
||||
'./playerWeekPoints.js',
|
||||
{
|
||||
name: entry[0],
|
||||
pointsThisWeek: entry[1]
|
||||
}
|
||||
).then(
|
||||
() => {
|
||||
++processedPlayerPointsWeek
|
||||
log(`Processed player ${processedPlayerPointsWeek}/${cache.pointsThisWeek.length} -> «${entry[0]}» got ${entry[1]} points this week!`)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
log("Processing players' points for the last month...")
|
||||
let processedPlayerPointsMonth = 0
|
||||
for (const entry of cache.pointsThisMonth) {
|
||||
spread(
|
||||
'./playerMonthPoints.js',
|
||||
{
|
||||
name: entry[0],
|
||||
pointsThisMonth: entry[1]
|
||||
}
|
||||
).then(
|
||||
() => {
|
||||
++processedPlayerPointsMonth
|
||||
log(`Processed player ${processedPlayerPointsMonth}/${cache.pointsThisMonth.length} -> «${entry[0]}» got ${entry[1]} points this month!`)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
import { randomUUID } from 'crypto'
|
||||
import { SHARE_ENV, Worker } from 'worker_threads'
|
||||
import initLog from './log.js'
|
||||
|
||||
const log = initLog("Worker Setup")
|
||||
|
||||
let workerFarm = []
|
||||
let workerReady = []
|
||||
let scheduledJobs = []
|
||||
|
||||
function scheduler() {
|
||||
if (scheduledJobs.length === 0) return
|
||||
|
||||
const readyIndex = workerReady.indexOf(true)
|
||||
if (readyIndex === -1) return
|
||||
|
||||
workerReady[readyIndex] = false
|
||||
const worker = workerFarm[readyIndex]
|
||||
|
||||
const job = scheduledJobs.shift()
|
||||
|
||||
worker.postMessage({
|
||||
type: 'runScript',
|
||||
script: job.script,
|
||||
data: job.data,
|
||||
id: job.jobID
|
||||
})
|
||||
|
||||
const messageHandler = message => {
|
||||
if (message.id === job.jobID) {
|
||||
workerReady[readyIndex] = true
|
||||
worker.removeListener(
|
||||
'message',
|
||||
messageHandler
|
||||
)
|
||||
return job.callback(message.result)
|
||||
}
|
||||
}
|
||||
|
||||
worker.on(
|
||||
'message',
|
||||
messageHandler
|
||||
)
|
||||
}
|
||||
|
||||
export function initWorkers(threads) {
|
||||
for (let i = 0; i < threads; ++i) {
|
||||
workerFarm.push(new Worker('./libs/utils/multithread/genericWorker.js', { env: SHARE_ENV }))
|
||||
|
||||
const worker = workerFarm[i]
|
||||
worker.postMessage({
|
||||
type: 'initWorker',
|
||||
name: `Worker ${parseInt(i) + 1}`
|
||||
})
|
||||
|
||||
workerReady[i] = true
|
||||
}
|
||||
|
||||
log(`Initialised ${threads} workers!`)
|
||||
|
||||
setInterval(
|
||||
scheduler,
|
||||
process.env.SCHEDULE_TIME ?? 50
|
||||
)
|
||||
|
||||
log(`Initialised the scheduler!`)
|
||||
}
|
||||
|
||||
export function spread(script, data) {
|
||||
return new Promise(
|
||||
async (resolve, reject) => {
|
||||
const jobID = randomUUID()
|
||||
|
||||
scheduledJobs.push({
|
||||
script,
|
||||
data,
|
||||
jobID,
|
||||
callback: result => {
|
||||
resolve(result)
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
import initLog from '../log.js'
|
||||
|
||||
const log = initLog('Fibonacci')
|
||||
|
||||
export function main(data) {
|
||||
return new Promise(
|
||||
(resolve, reject) => {
|
||||
let nums = [1, 1]
|
||||
|
||||
for (let i = 0; i < 44; i++) {
|
||||
nums.push(nums[nums.length - 2] + nums[nums.length - 1])
|
||||
}
|
||||
|
||||
let primes = []
|
||||
for (const num of nums) {
|
||||
let isPrime = true
|
||||
for (let i = 2; i < num / 2; ++i) {
|
||||
if (num % i === 0)
|
||||
isPrime = false
|
||||
}
|
||||
|
||||
if (isPrime)
|
||||
primes.push(num)
|
||||
}
|
||||
|
||||
resolve(primes)
|
||||
}
|
||||
)
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
import { workerData, parentPort } from 'worker_threads'
|
||||
import initLog from '../log.js'
|
||||
|
||||
let runScript = ''
|
||||
let myName = ''
|
||||
|
||||
let log = initLog(myName)
|
||||
|
||||
parentPort.on(
|
||||
'message',
|
||||
async message => {
|
||||
switch (message.type) {
|
||||
case 'initWorker':
|
||||
myName = message.name
|
||||
log = initLog(myName)
|
||||
process.env.DEBUG && log(`Started new thread -> «${myName}»`)
|
||||
break
|
||||
|
||||
case 'runScript':
|
||||
runScript = message.script
|
||||
process.env.DEBUG && log(`Running script -> «${runScript}»`)
|
||||
|
||||
import(runScript).then(
|
||||
script => script.main(message.data).then(
|
||||
result => {
|
||||
parentPort.postMessage({ result, id: message.id })
|
||||
process.env.DEBUG && log(`Script done -> «${runScript}»`)
|
||||
}
|
||||
)
|
||||
)
|
||||
break
|
||||
|
||||
default:
|
||||
log(`Invalid message -> ${message.type ?? 'No message type provided!'}`)
|
||||
break
|
||||
}
|
||||
}
|
||||
)
|
|
@ -1,11 +0,0 @@
|
|||
import mongoose from 'mongoose'
|
||||
|
||||
export async function connectMongoose() {
|
||||
await mongoose.connect(
|
||||
process.env.MONGO_URI,
|
||||
{
|
||||
useNewUrlParser: true,
|
||||
useUnifiedTopology: true
|
||||
}
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
import Player from '../../../schemas/Player.js'
|
||||
import { connectMongoose } from './mongoForWorkes.js'
|
||||
|
||||
connectMongoose()
|
||||
|
||||
export function main(data) {
|
||||
return new Promise(
|
||||
(resolve, reject) => {
|
||||
Player.findOneAndUpdate(
|
||||
{ name: data.name },
|
||||
{ rankPoints: data.pointsThisMonth }
|
||||
).then(
|
||||
() => resolve()
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
import Player from '../../../schemas/Player.js'
|
||||
import { connectMongoose } from './mongoForWorkes.js'
|
||||
|
||||
connectMongoose()
|
||||
|
||||
export function main(data) {
|
||||
return new Promise(
|
||||
(resolve, reject) => {
|
||||
Player.findOneAndUpdate(
|
||||
{ name: data.name },
|
||||
{ points: data.points }
|
||||
).then(
|
||||
() => resolve()
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
import Player from '../../../schemas/Player.js'
|
||||
import { connectMongoose } from './mongoForWorkes.js'
|
||||
|
||||
connectMongoose()
|
||||
|
||||
export function main(data) {
|
||||
return new Promise(
|
||||
(resolve, reject) => {
|
||||
Player.findOneAndUpdate(
|
||||
{ name: data.name },
|
||||
{ rankPoints: data.rankPoints }
|
||||
).then(
|
||||
() => resolve()
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
import Player from '../../../schemas/Player.js'
|
||||
import { connectMongoose } from './mongoForWorkes.js'
|
||||
|
||||
connectMongoose()
|
||||
|
||||
export function main(data) {
|
||||
return new Promise(
|
||||
(resolve, reject) => {
|
||||
Player.findOneAndUpdate(
|
||||
{ name: data.name },
|
||||
{ teamPoints: data.teamPoints }
|
||||
).then(
|
||||
() => resolve()
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
import Player from '../../../schemas/Player.js'
|
||||
import { connectMongoose } from './mongoForWorkes.js'
|
||||
|
||||
connectMongoose()
|
||||
|
||||
export function main(data) {
|
||||
return new Promise(
|
||||
(resolve, reject) => {
|
||||
Player.findOneAndUpdate(
|
||||
{ name: data.name },
|
||||
{ pointsThisWeek: data.pointsThisWeek }
|
||||
).then(
|
||||
() => resolve()
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
import mongoose from 'mongoose'
|
||||
|
||||
const Finish = new mongoose.Schema({
|
||||
map: String,
|
||||
time: Number,
|
||||
date: Date,
|
||||
serverLocation: String,
|
||||
player: String
|
||||
})
|
||||
|
||||
Finish.index({ player: 1, map: 1 })
|
||||
|
||||
/**
|
||||
* This cotains the mongoose 'Finish' model.
|
||||
* @module schemas/Finish
|
||||
*/
|
||||
export default mongoose.model("Finish", Finish)
|
|
@ -1,17 +0,0 @@
|
|||
import mongoose from 'mongoose'
|
||||
|
||||
const Level = new mongoose.Schema({
|
||||
name: String,
|
||||
mapper: String,
|
||||
release: Date,
|
||||
category: String,
|
||||
rating: Number,
|
||||
awardPoints: Number,
|
||||
totalFinishes: Number
|
||||
})
|
||||
|
||||
/**
|
||||
* This cotains the mongoose 'Level' (maps) model.
|
||||
* @module schemas/Level
|
||||
*/
|
||||
export default mongoose.model("Level", Level)
|
|
@ -1,19 +0,0 @@
|
|||
import mongoose from 'mongoose'
|
||||
|
||||
const Player = new mongoose.Schema({
|
||||
name: String,
|
||||
points: Number,
|
||||
rankPoints: Number,
|
||||
teamPoints: Number,
|
||||
pointsThisWeek: Number,
|
||||
pointsThisMonth: Number,
|
||||
firstFinish: Date
|
||||
})
|
||||
|
||||
Player.index({ name: 1 })
|
||||
|
||||
/**
|
||||
* This cotains the mongoose 'Player' model.
|
||||
* @module schemas/Player
|
||||
*/
|
||||
export default mongoose.model("Player", Player)
|
|
@ -1,15 +0,0 @@
|
|||
import mongoose from 'mongoose'
|
||||
|
||||
const TeamFinish = new mongoose.Schema({
|
||||
map: String,
|
||||
time: Number,
|
||||
date: Date,
|
||||
serverLocation: String,
|
||||
players: [ String ]
|
||||
})
|
||||
|
||||
/**
|
||||
* This cotains the mongoose 'TeamFinish' model.
|
||||
* @module schemas/TeamFinish
|
||||
*/
|
||||
export default mongoose.model("TeamFinish", TeamFinish)
|
|
@ -1,67 +0,0 @@
|
|||
import { initWorkers, spread } from '../libs/utils/multithread.js'
|
||||
import Player from '../schemas/Player.js'
|
||||
import decodeMsgpack from '../libs/database/sqlite2mongo/decodeMsgpack.js'
|
||||
import initLog from '../libs/utils/log.js'
|
||||
|
||||
const log = initLog("Fib. Test")
|
||||
|
||||
initWorkers(3)
|
||||
|
||||
const jobs = 10
|
||||
let completed = 0
|
||||
for (let i = 0; i < jobs; ++i) {
|
||||
spread(
|
||||
'./fibonacci.js',
|
||||
{}
|
||||
).then(
|
||||
result => {
|
||||
++completed
|
||||
log(`Completed job ${completed}/${jobs} -> ${result}`)
|
||||
|
||||
if (completed === jobs) process.exit(0)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export default async function() {
|
||||
const cache = decodeMsgpack()
|
||||
|
||||
await Player.updateMany(
|
||||
{},
|
||||
{
|
||||
pointsThisWeek: 0,
|
||||
pointsThisMonth: 0
|
||||
}
|
||||
)
|
||||
|
||||
let processedPlayers = 0
|
||||
const totalPlayers = cache.pointsRanks.length
|
||||
const rawDbFunc = (name, points) => new Promise((resolve, reject) => Player.findOneAndUpdate({ name: name }, { points: points }).then(() => resolve()))
|
||||
for (const entry of cache.pointsRanks) {
|
||||
let data = new SharedArrayBuffer(1024 * 10)
|
||||
// let data = new Array(buffer)
|
||||
|
||||
data[0] = 0
|
||||
data[1] = entry[0]
|
||||
data[2] = entry[1]
|
||||
|
||||
spread(
|
||||
'./db.test.js',
|
||||
data
|
||||
).then(
|
||||
result => {
|
||||
console.log(data[0])
|
||||
++processedPlayers
|
||||
log(`Process player ${processedPlayers}/${totalPlayers} -> «${entry[0]}» with ${entry[1]} points!`)
|
||||
|
||||
if (processedPlayers === totalPlayers)
|
||||
process.exit(0)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user