diff --git a/src/client/client.ts b/src/client/client.ts index 3923176..dd2ca81 100644 --- a/src/client/client.ts +++ b/src/client/client.ts @@ -1,6 +1,7 @@ import { Router } from 'express' -import weapons from './weapons' -import player from './player' +import serverWeapons from './serverWeapons' +import playerWeapons from './playerWeapons' +import serverPlayers from './serverPlayers' const router = Router() //timeout middleware ? router.get('/*', (req, res, next) => { @@ -16,8 +17,8 @@ router.get('/players/:playerId', (req, res, next) => {}) router.get('/servers/', (req, res, next) => {}) router.get('/servers/:serverId/', (req, res, next) => {}) -router.get('/servers/:serverId/players', (req, res, next) => {}) -router.get('/servers/:serverId/player/:playerId', player) +router.get('/servers/:serverId/players', serverPlayers) +router.get('/servers/:serverId/player/:playerId', playerWeapons) -router.use('/servers/:serverId/weapons', weapons) +router.use('/servers/:serverId/weapons', serverWeapons) export default router diff --git a/src/client/player.ts b/src/client/playerWeapons.ts similarity index 84% rename from src/client/player.ts rename to src/client/playerWeapons.ts index dd9cb5c..fb53e2e 100644 --- a/src/client/player.ts +++ b/src/client/playerWeapons.ts @@ -14,21 +14,25 @@ const middlewares: RequestHandler[] = [ const server = Number(req.params.serverId) const player = Number(req.params.playerId) await processPlayerWeapons(server, player) - const killsData = await cache.HGETALL( - `servers:${server}:players:${player}:weapons:kills` - ) - const deathData = await cache.HGETALL( - `servers:${server}:players:${player}:weapons:deaths` - ) - const data: { [x: string]: { kills: string; deaths: string } } = {} - Object.keys(killsData).forEach((key) => { - data[key] = { kills: killsData[key], deaths: deathData[key] } - }) - + const data = await getPlayerWeapons(server, player) res.status(200).send(data) } ] +async function getPlayerWeapons(server: number, player: number) { + const killsData = await cache.HGETALL( + `servers:${server}:players:${player}:weapons:kills` + ) + const deathData = await cache.HGETALL( + `servers:${server}:players:${player}:weapons:deaths` + ) + const data: { [x: string]: { kills: string; deaths: string } } = {} + Object.keys(killsData).forEach((key) => { + data[key] = { kills: killsData[key], deaths: deathData[key] } + }) + return data +} + async function processPlayerWeapons(server: number, player: number) { let last_entry = Number( diff --git a/src/client/serverPlayers.ts b/src/client/serverPlayers.ts new file mode 100644 index 0000000..2e1e7b0 --- /dev/null +++ b/src/client/serverPlayers.ts @@ -0,0 +1,88 @@ +import { RequestHandler } from 'express' +import { param } from 'express-validator' +import { validateErrors } from '../common' +import cache from '../cache/redis' +import { sql } from 'kysely' +import db from '../db/db' + +const { count, max } = db.fn + +const middlewares: RequestHandler[] = [ + param('serverId').exists().toInt().isInt(), + validateErrors, + async (req, res) => { + const server = Number(req.params.serverId) + await processServerPlayers(server) + let data = await getServerPlayers(server) + res.status(200).send(data) + } +] + +async function getServerPlayers(server: number) { + const killsData = await cache.HGETALL(`servers:${server}:players:kills`) + const deathData = await cache.HGETALL(`servers:${server}:players:deaths`) + const data: { [x: string]: { kills: string; deaths: string } } = {} + Object.keys(killsData).forEach((key) => { + data[key] = { kills: killsData[key], deaths: deathData[key] } + }) + return data +} + +async function processServerPlayers(server: number) { + let last_entry = + Number(await cache.HGET(`servers:${server}:players`, 'last_entry')) || 0 + const newData = await db + .with('killdata', () => + db + .selectFrom('kill') + .select([count('kill.id').as('num_kills'), 'kill.attacker_id']) + .where('kill.id', '>', last_entry) + .where('kill.server', '=', server) + .whereRef('attacker_id', '!=', 'victim_id') + .groupBy('attacker_id') + ) + .with('deathdata', () => + db + .selectFrom('kill') + .select([count('kill.id').as('num_deaths'), 'kill.victim_id']) + .where('kill.id', '>', last_entry) + .where('kill.server', '=', server) + .groupBy('victim_id') + ) + .selectFrom('killdata') + .select([ + sql`coalesce(killdata.num_kills, 0)`.as('kills'), + sql`coalesce(deathdata.num_deaths, 0)`.as('deaths'), + sql`COALESCE(killdata.attacker_id, deathdata.victim_id)`.as( + 'player' + ), + db + .selectFrom('kill') + .select(max('kill.id').as('last_entry')) + .as('last_entry') + ]) + .fullJoin('deathdata', 'deathdata.victim_id', 'killdata.attacker_id') + .orderBy('kills', 'desc') + .execute() + //if no new kills + if (newData.length == 0) { + return + } + last_entry = newData.reduce( + (acc, current) => (current.last_entry > acc ? current.last_entry : acc), + 0 + ) + const promises: Promise[] = [] + newData.forEach(({ kills, deaths, player }) => { + promises.push( + cache.HINCRBY(`servers:${server}:players:kills`, player, kills), + cache.HINCRBY(`servers:${server}:players:deaths`, player, deaths) + ) + }) + promises.push( + cache.HSET(`servers:${server}:players`, 'last_entry', newData[0].last_entry) + ) + await Promise.all(promises) +} + +export default middlewares diff --git a/src/client/weapons.ts b/src/client/serverWeapons.ts similarity index 100% rename from src/client/weapons.ts rename to src/client/serverWeapons.ts