175 lines
8.0 KiB
JavaScript
175 lines
8.0 KiB
JavaScript
'use strict';
|
|
|
|
// modules
|
|
const express = require('express');
|
|
|
|
// HTTP status codes by name
|
|
const codes = require('./http-codes');
|
|
|
|
const routerHandling = require('../middleware/router-handling');
|
|
|
|
// Mongoose Model using mongoDB
|
|
const CampaignModel = require('../models/campaign');
|
|
const PlayerModel = require('../models/player');
|
|
const WarModel = require('../models/war');
|
|
|
|
// Util
|
|
const isSteamUUID = require('../tools/util').isSteamUUID;
|
|
|
|
const campaignPlayer = new express.Router();
|
|
|
|
// routes **********************
|
|
campaignPlayer.route('/ranking/:campaignId')
|
|
.get((req, res, next) => {
|
|
WarModel.find({campaign: req.params.campaignId}, '_id', (err, wars) => {
|
|
if (err) return next(err);
|
|
const warIds = wars.map((obj) => {
|
|
return obj._id;
|
|
});
|
|
WarModel.findOne({campaign: req.params.campaignId}, {}, {sort: {'date': -1}}, (err, latestWar) => {
|
|
PlayerModel.find({warId: {'$in': warIds}}, (err, items) => {
|
|
if (err) return next(err);
|
|
if (!items || items.length === 0) {
|
|
const err = new Error('No players for given campaignId');
|
|
err.status = codes.notfound;
|
|
return next(err);
|
|
}
|
|
|
|
const rankingItems = [];
|
|
|
|
// check only first player to have valid steamUUID - then decide if tracked by name or by ID
|
|
const usesUUID = isSteamUUID(items[0].steamUUID);
|
|
|
|
new Set(items.map(usesUUID ? (x) => x.steamUUID : (x) => x.name))
|
|
.forEach((player) => {
|
|
const playerInstances = items.filter(
|
|
usesUUID ? (p) => p.steamUUID === player : (p) => p.name === player);
|
|
const resItem = {
|
|
name: usesUUID ? playerInstances[playerInstances.length - 1].name : player,
|
|
kill: 0,
|
|
vehicleLight: 0,
|
|
vehicleHeavy: 0,
|
|
vehicleAir: 0,
|
|
death: 0,
|
|
friendlyFire: 0,
|
|
revive: 0,
|
|
respawn: 0,
|
|
flagTouch: 0,
|
|
travelDistance: 0,
|
|
driverDistance: 0,
|
|
};
|
|
for (let i = 0; i < playerInstances.length; i++) {
|
|
const player = playerInstances[i];
|
|
resItem.kill += player.kill;
|
|
resItem.death += player.death;
|
|
resItem.friendlyFire += player.friendlyFire;
|
|
resItem.vehicleLight += player.vehicleLight;
|
|
resItem.vehicleHeavy += player.vehicleHeavy;
|
|
resItem.vehicleAir += player.vehicleAir;
|
|
resItem.revive += player.revive;
|
|
resItem.respawn += player.respawn;
|
|
resItem.flagTouch += player.flagTouch;
|
|
if (player.travelDistance) {
|
|
resItem.travelDistance += Math.round(player.travelDistance / 1000); // meters -> km
|
|
}
|
|
if (player.driverDistance) {
|
|
resItem.driverDistance += Math.round(player.driverDistance / 1000); // meters -> km
|
|
}
|
|
}
|
|
resItem.warCount = playerInstances.length;
|
|
|
|
const latestPlayerFraction = playerInstances[playerInstances.length - 1].fraction;
|
|
resItem.fraction =
|
|
(latestPlayerFraction === 'OPFOR') ?
|
|
latestWar.fractionMappingOpfor :
|
|
latestWar.fractionMappingBlufor;
|
|
|
|
rankingItems.push(resItem);
|
|
});
|
|
|
|
const getSortedField = (fieldName) => {
|
|
let num = 1;
|
|
const filteredSortResult = rankingItems.map((item) => {
|
|
return {
|
|
name: item.name,
|
|
fraction: item.fraction,
|
|
[fieldName]: item[fieldName],
|
|
};
|
|
})
|
|
.sort((a, b) => b[fieldName] - a[fieldName]);
|
|
const res = JSON.parse(JSON.stringify(filteredSortResult));
|
|
for (const entity of res) {
|
|
entity.num = num++;
|
|
}
|
|
return res;
|
|
};
|
|
|
|
res.locals.items = {
|
|
kill: getSortedField('kill'),
|
|
death: getSortedField('death'),
|
|
friendlyFire: getSortedField('friendlyFire'),
|
|
vehicleLight: getSortedField('vehicleLight'),
|
|
vehicleHeavy: getSortedField('vehicleHeavy'),
|
|
vehicleAir: getSortedField('vehicleAir'),
|
|
revive: getSortedField('revive'),
|
|
respawn: getSortedField('respawn'),
|
|
flagTouch: getSortedField('flagTouch'),
|
|
travelDistance: getSortedField('travelDistance'),
|
|
driverDistance: getSortedField('driverDistance'),
|
|
warCount: getSortedField('warCount'),
|
|
};
|
|
next();
|
|
});
|
|
});
|
|
});
|
|
})
|
|
|
|
.all(
|
|
routerHandling.httpMethodNotAllowed
|
|
);
|
|
|
|
campaignPlayer.route('/single/:campaignId/:playerId')
|
|
.get((req, res, next) => {
|
|
CampaignModel.findById(req.params.campaignId, (err, campaign) => {
|
|
if (err) return next(err);
|
|
WarModel.find({campaign: req.params.campaignId}, '_id', (err, wars) => {
|
|
if (err) return next(err);
|
|
const warIds = wars.map((obj) => {
|
|
return obj._id;
|
|
});
|
|
|
|
// find by player name until v1.6.12, afterwards by SteamUUID
|
|
const playerId = req.params.playerId;
|
|
const filter = {};
|
|
filter[isSteamUUID(playerId) ? 'steamUUID' : 'name'] = playerId;
|
|
filter['warId'] = {'$in': warIds};
|
|
|
|
PlayerModel.find(filter)
|
|
.populate('warId')
|
|
.exec((err, items) => {
|
|
if (err) return next(err);
|
|
if (!items || items.length === 0) {
|
|
const err = new Error('Unknown player id');
|
|
err.status = codes.notfound;
|
|
return next(err);
|
|
}
|
|
res.locals.items = {
|
|
name: items[items.length - 1].name,
|
|
campaign: campaign,
|
|
players: items,
|
|
};
|
|
next();
|
|
});
|
|
});
|
|
});
|
|
})
|
|
|
|
.all(
|
|
routerHandling.httpMethodNotAllowed
|
|
);
|
|
|
|
|
|
campaignPlayer.use(routerHandling.emptyResponse);
|
|
|
|
module.exports = campaignPlayer;
|