From d18986cb1f2e574fe86ff6f67b5e587e8ec8c92a Mon Sep 17 00:00:00 2001 From: HardiReady Date: Sat, 3 Mar 2018 12:26:24 +0100 Subject: [PATCH] Modify parsing and models to catch vehicle kills --- api/models/logs/vehicle.js | 34 ++++++++++++++++++++++++ api/models/player.js | 6 +++++ api/routes/wars.js | 52 ++++++++++++++++++++----------------- api/tools/log-parse-tool.js | 51 +++++++++++++++++++++++++++++------- 4 files changed, 109 insertions(+), 34 deletions(-) create mode 100644 api/models/logs/vehicle.js diff --git a/api/models/logs/vehicle.js b/api/models/logs/vehicle.js new file mode 100644 index 0000000..616f84c --- /dev/null +++ b/api/models/logs/vehicle.js @@ -0,0 +1,34 @@ +"use strict"; + +const mongoose = require('mongoose'); +const Schema = mongoose.Schema; + +const LogVehicleKillSchema = new Schema({ + war: { + type: mongoose.Schema.Types.ObjectId, + ref: 'War', + required: true + }, + time: { + type: Date, + required: true + }, + shooter: { + type: String + }, + target: { + type: String, + required: true + }, + fraction: { + type: String, + enum: ['BLUFOR', 'OPFOR', 'NONE'], + required: true + } +}, { + collection: 'logVehicle' +}); +// optional more indices +LogVehicleKillSchema.index({war: 1, shooter: 1, target: 1}); + +module.exports = mongoose.model('LogVehicle', LogVehicleKillSchema); diff --git a/api/models/player.js b/api/models/player.js index 176b602..6741289 100644 --- a/api/models/player.js +++ b/api/models/player.js @@ -24,6 +24,12 @@ const PlayerSchema = new Schema({ set: v => Math.round(v), required: true }, + vehicle: { + type: Number, + get: v => Math.round(v), + set: v => Math.round(v), + required: true + }, death: { type: Number, get: v => Math.round(v), diff --git a/api/routes/wars.js b/api/routes/wars.js index a253acf..406312f 100644 --- a/api/routes/wars.js +++ b/api/routes/wars.js @@ -27,6 +27,7 @@ const CampaignModel = require('../models/campaign'); const WarModel = require('../models/war'); const PlayerModel = require('../models/player'); const LogKillModel = require('../models/logs/kill'); +const LogVehicleKillModel = require('../models/logs/vehicle'); const LogRespawnModel = require('../models/logs/respawn'); const LogReviveModel = require('../models/logs/revive'); const LogTransportModel = require('../models/logs/transport'); @@ -92,33 +93,36 @@ wars.route('/') return next(err); } LogKillModel.create(statsResult.kills, function () { - LogRespawnModel.create(statsResult.respawn, function () { - LogReviveModel.create(statsResult.revive, function () { - LogFlagModel.create(statsResult.flag, function () { - LogBudgetModel.create(statsResult.budget, function () { - LogTransportModel.create(statsResult.transport, function () { - LogPointsModel.create(statsResult.points, function () { - const folderName = __dirname + '/../resource/logs/' + war._id; - mkdirp(folderName, function (err) { - if (err) return next(err); + LogVehicleKillModel.create(statsResult.vehicles, function () { - // save clean log file - const cleanFile = fs.createWriteStream(folderName + '/clean.log'); - statsResult.clean.forEach(cleanLine => { - cleanFile.write(cleanLine + '\n\n') - }); - cleanFile.end(); + LogRespawnModel.create(statsResult.respawn, function () { + LogReviveModel.create(statsResult.revive, function () { + LogFlagModel.create(statsResult.flag, function () { + LogBudgetModel.create(statsResult.budget, function () { + LogTransportModel.create(statsResult.transport, function () { + LogPointsModel.create(statsResult.points, function () { + const folderName = __dirname + '/../resource/logs/' + war._id; + mkdirp(folderName, function (err) { + if (err) return next(err); - // save raw log file - const rawFile = fs.createWriteStream(folderName + '/war.log'); - lineArray.forEach(rawLine => { - rawFile.write(rawLine + '\n') - }); - rawFile.end(); + // save clean log file + const cleanFile = fs.createWriteStream(folderName + '/clean.log'); + statsResult.clean.forEach(cleanLine => { + cleanFile.write(cleanLine + '\n\n') + }); + cleanFile.end(); - res.status(codes.created); - res.locals.items = war; - next(); + // save raw log file + const rawFile = fs.createWriteStream(folderName + '/war.log'); + lineArray.forEach(rawLine => { + rawFile.write(rawLine + '\n') + }); + rawFile.end(); + + res.status(codes.created); + res.locals.items = war; + next(); + }) }) }) }) diff --git a/api/tools/log-parse-tool.js b/api/tools/log-parse-tool.js index 4cbd082..af622d2 100644 --- a/api/tools/log-parse-tool.js +++ b/api/tools/log-parse-tool.js @@ -13,6 +13,7 @@ const parseWarLog = (lineArray, war) => { budget: [], points: [], kills: [], + vehicles: [], respawn: [], revive: [], flag: [], @@ -40,21 +41,35 @@ const parseWarLog = (lineArray, war) => { /** * KILLS */ - if (line.includes('(Abschuss)') && !line.includes('Fahrzeug')) { + if (line.includes('(Abschuss)')) { stats.clean.push(line); + const shooterString = line.substring(line.lastIndexOf(' von: ') + 6, line.lastIndexOf('."')); const shooter = getPlayerAndFractionFromString(shooterString); const targetString = line.substring(line.lastIndexOf(' --- ') + 5, line.lastIndexOf(' von:')); - const target = getPlayerAndFractionFromString(targetString); - stats.kills.push({ - war: war._id, - time: getFullTimeDate(war.date, line.split(WHITESPACE)[5]), - shooter: shooter ? shooter.name : null, - target: target ? target.name : null, - friendlyFire: shooter ? target.fraction === shooter.fraction : false, - fraction: shooter ? shooter.fraction : 'NONE' - }); + if (line.includes('Fahrzeug')) { + const target = getVehicleAndFractionFromString(targetString); + if (target && shooter && target.fraction !== shooter.fraction) { + stats.vehicles.push({ + war: war._id, + time: getFullTimeDate(war.date, line.split(WHITESPACE)[5]), + shooter: shooter ? shooter.name : null, + target: target ? target.name : null, + fraction: shooter ? shooter.fraction : 'NONE' + }) + } + } else { + const target = getPlayerAndFractionFromString(targetString); + stats.kills.push({ + war: war._id, + time: getFullTimeDate(war.date, line.split(WHITESPACE)[5]), + shooter: shooter ? shooter.name : null, + target: target ? target.name : null, + friendlyFire: shooter ? target.fraction === shooter.fraction : false, + fraction: shooter ? shooter.fraction : 'NONE' + }); + } } /** @@ -181,6 +196,7 @@ const parseWarLog = (lineArray, war) => { const playerName = stats.players[i].name; stats.players[i]['respawn'] = stats.respawn.filter(res => res.player === playerName).length; stats.players[i]['kill'] = stats.kills.filter(kill => kill.shooter === playerName && !kill.friendlyFire).length; + stats.players[i]['vehicle'] = stats.vehicles.filter(vehicle => vehicle.shooter === playerName).length; stats.players[i]['friendlyFire'] = stats.kills.filter(kill => kill.shooter === playerName && kill.friendlyFire).length; stats.players[i]['death'] = stats.kills.filter(kill => kill.target === playerName).length; stats.players[i]['revive'] = stats.revive.filter(rev => rev.medic === playerName && !rev.stabilized).length; @@ -233,6 +249,21 @@ const getPlayerAndFractionFromString = (nameAndFractionString) => { } }; +const getVehicleAndFractionFromString = (nameAndFractionString) => { + const nameArray = nameAndFractionString.trim().split(WHITESPACE); + const fractionPart = nameArray[nameArray.length - 1]; + + // escape it is some parachute fraction identifier + if (fractionPart === 'OPF_F' || fractionPart === 'BLU_F') { + return; + } + + const fraction = fractionPart === '(OPT_NATO)' || fractionPart === '(OPT_NATO_T)' ? 'BLUFOR' : 'OPFOR'; + const name = nameAndFractionString.substring(0, nameAndFractionString.indexOf(fractionPart) - 1); + + return {name: name, fraction: fraction}; +}; + const transformMoneyString = (budgetString) => { if (!budgetString.includes('e+')) { return parseInt(budgetString);