Add parsing and persisting for FPS logs (CC-80)
parent
7c23c302c6
commit
03073f5436
Binary file not shown.
|
@ -32,7 +32,7 @@ const LogBudgetSchema = new Schema({
|
|||
},
|
||||
}, {
|
||||
collection: 'logBudget',
|
||||
versionKey: false
|
||||
versionKey: false,
|
||||
});
|
||||
// optional more indices
|
||||
LogBudgetSchema.index({war: 1});
|
||||
|
|
|
@ -28,7 +28,7 @@ const LogFlagSchema = new Schema({
|
|||
},
|
||||
}, {
|
||||
collection: 'logFlag',
|
||||
versionKey: false
|
||||
versionKey: false,
|
||||
});
|
||||
// optional more indices
|
||||
LogFlagSchema.index({war: 1, player: 1});
|
||||
|
|
|
@ -40,7 +40,7 @@ const LogKillSchema = new Schema({
|
|||
},
|
||||
}, {
|
||||
collection: 'logKill',
|
||||
versionKey: false
|
||||
versionKey: false,
|
||||
});
|
||||
// optional more indices
|
||||
LogKillSchema.index({war: 1, shooter: 1, target: 1});
|
||||
|
|
|
@ -27,7 +27,7 @@ const LogPlayerCountSchema = new Schema({
|
|||
},
|
||||
}, {
|
||||
collection: 'logPlayerCount',
|
||||
versionKey: false
|
||||
versionKey: false,
|
||||
});
|
||||
// optional more indices
|
||||
LogPlayerCountSchema.index({war: 1});
|
||||
|
|
|
@ -32,7 +32,7 @@ const LogKillSchema = new Schema({
|
|||
},
|
||||
}, {
|
||||
collection: 'logPoints',
|
||||
versionKey: false
|
||||
versionKey: false,
|
||||
});
|
||||
// optional more indices
|
||||
LogKillSchema.index({war: 1, shooter: 1, target: 1});
|
||||
|
|
|
@ -19,7 +19,7 @@ const LogRespawnSchema = new Schema({
|
|||
},
|
||||
}, {
|
||||
collection: 'logRespawn',
|
||||
versionKey: false
|
||||
versionKey: false,
|
||||
});
|
||||
// optional more indices
|
||||
LogRespawnSchema.index({war: 1, player: 1});
|
||||
|
|
|
@ -32,7 +32,7 @@ const LogReviveSchema = new Schema({
|
|||
},
|
||||
}, {
|
||||
collection: 'logRevive',
|
||||
versionKey: false
|
||||
versionKey: false,
|
||||
});
|
||||
// optional more indices
|
||||
LogReviveSchema.index({war: 1, medic: 1});
|
||||
|
|
|
@ -13,6 +13,18 @@ const LogServerFpsSchema = new Schema({
|
|||
type: String,
|
||||
required: true,
|
||||
},
|
||||
singleAvgFps: {
|
||||
type: Number,
|
||||
get: (v) => Math.round(v),
|
||||
set: (v) => Math.round(v),
|
||||
required: true,
|
||||
},
|
||||
singleMinFps: {
|
||||
type: Number,
|
||||
get: (v) => Math.round(v),
|
||||
set: (v) => Math.round(v),
|
||||
required: true,
|
||||
},
|
||||
avgFps: [{
|
||||
type: Number,
|
||||
get: (v) => Math.round(v),
|
||||
|
@ -27,7 +39,7 @@ const LogServerFpsSchema = new Schema({
|
|||
}],
|
||||
}, {
|
||||
collection: 'logServerFps',
|
||||
versionKey: false
|
||||
versionKey: false,
|
||||
});
|
||||
// optional more indices
|
||||
LogServerFpsSchema.index({war: 1});
|
||||
|
|
|
@ -34,7 +34,7 @@ const LogTransportSchema = new Schema({
|
|||
},
|
||||
}, {
|
||||
collection: 'logTransport',
|
||||
versionKey: false
|
||||
versionKey: false,
|
||||
});
|
||||
// optional more indices
|
||||
LogTransportSchema.index({war: 1, driver: 1});
|
||||
|
|
|
@ -41,7 +41,7 @@ const LogVehicleKillSchema = new Schema({
|
|||
},
|
||||
}, {
|
||||
collection: 'logVehicle',
|
||||
versionKey: false
|
||||
versionKey: false,
|
||||
});
|
||||
// optional more indices
|
||||
LogVehicleKillSchema.index({war: 1, shooter: 1, target: 1});
|
||||
|
|
|
@ -82,6 +82,11 @@ const PlayerSchema = new Schema({
|
|||
get: (v) => Math.round(v),
|
||||
set: (v) => Math.round(v),
|
||||
},
|
||||
performance: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'LogServerFpsSchema',
|
||||
required: true,
|
||||
},
|
||||
}, {
|
||||
collection: 'player',
|
||||
timestamps: {createdAt: 'timestamp'},
|
||||
|
|
|
@ -34,6 +34,7 @@ const LogFlagModel = require('../models/logs/flag');
|
|||
const LogBudgetModel = require('../models/logs/budget');
|
||||
const LogPointsModel = require('../models/logs/points');
|
||||
const LogPlayerCountModel = require('../models/logs/player-count');
|
||||
const LogServerFpsModel = require('../models/logs/server-fps');
|
||||
|
||||
// util
|
||||
const genericPatch = require('./_generic').genericPatch;
|
||||
|
@ -59,25 +60,20 @@ wars.route('/')
|
|||
})
|
||||
|
||||
.post(apiAuthenticationMiddleware, checkMT, upload.single('log'), (req, res, next) => {
|
||||
const body = req.body;
|
||||
const warBody = new WarModel(body);
|
||||
const body = req.body;
|
||||
const warBody = new WarModel(body);
|
||||
|
||||
if (req.file) {
|
||||
fs.readFile(req.file.buffer, (file, err) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
const lineArray = file.toString().split('\n');
|
||||
const statsResult = parseWarLog(lineArray, warBody);
|
||||
statsResult.war.save((err, war) => {
|
||||
if (req.file) {
|
||||
fs.readFile(req.file.buffer, (file, err) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
PlayerModel.create(statsResult.players, (err) => {
|
||||
const lineArray = file.toString().split('\n');
|
||||
const statsResult = parseWarLog(lineArray, warBody);
|
||||
statsResult.war.save((err, war) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
LogKillModel.create(statsResult.kills, () => {
|
||||
LogVehicleKillModel.create(statsResult.vehicles, () => {
|
||||
LogRespawnModel.create(statsResult.respawn, () => {
|
||||
|
@ -87,27 +83,43 @@ wars.route('/')
|
|||
LogTransportModel.create(statsResult.transport, () => {
|
||||
LogPlayerCountModel.create(statsResult.playerCount, () => {
|
||||
LogPointsModel.create(statsResult.points, () => {
|
||||
const folderName = resourceLocation.concat(war._id);
|
||||
mkdirp(folderName, (err) => {
|
||||
if (err) return next(err);
|
||||
|
||||
// save clean log file
|
||||
const cleanFile = fs.createWriteStream(folderName + '/clean.log');
|
||||
statsResult.clean.forEach((cleanLine) => {
|
||||
cleanFile.write(cleanLine + '\n\n');
|
||||
LogServerFpsModel.create(statsResult.serverFps, (err, serverPerformanceEntries) => {
|
||||
serverPerformanceEntries.forEach((entry) => {
|
||||
const idx = statsResult.players
|
||||
.findIndex((player) => player.name === entry.entityName);
|
||||
if (idx !== -1) {
|
||||
const player = statsResult.players[idx];
|
||||
player['performance'] = entry._id;
|
||||
statsResult.players[idx] = player;
|
||||
}
|
||||
});
|
||||
cleanFile.end();
|
||||
PlayerModel.create(statsResult.players, (err) => {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
const folderName = resourceLocation.concat(war._id);
|
||||
mkdirp(folderName, (err) => {
|
||||
if (err) return next(err);
|
||||
|
||||
// save raw log file
|
||||
const rawFile = fs.createWriteStream(folderName + '/war.log');
|
||||
lineArray.forEach((rawLine) => {
|
||||
rawFile.write(rawLine + '\n');
|
||||
// save clean log file
|
||||
const cleanFile = fs.createWriteStream(folderName + '/clean.log');
|
||||
statsResult.clean.forEach((cleanLine) => {
|
||||
cleanFile.write(cleanLine + '\n\n');
|
||||
});
|
||||
cleanFile.end();
|
||||
|
||||
// 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();
|
||||
});
|
||||
});
|
||||
rawFile.end();
|
||||
|
||||
res.status(codes.created);
|
||||
res.locals.items = war;
|
||||
next();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -120,13 +132,13 @@ wars.route('/')
|
|||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
const err = new Error('no Logfile provided');
|
||||
err.status = codes.wrongmediasend;
|
||||
next(err);
|
||||
} else {
|
||||
const err = new Error('no Logfile provided');
|
||||
err.status = codes.wrongmediasend;
|
||||
next(err);
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
.all(
|
||||
routerHandling.httpMethodNotAllowed
|
||||
|
|
|
@ -27,7 +27,15 @@ const bluforPlayerCountRegex = /NATO\s(\d*)/;
|
|||
|
||||
const opforPlayerCountRegex = /CSAT\s(\d*)/;
|
||||
|
||||
const timestampRegex= /LOG:\s(\d*:\d*:\d*)\s---/;
|
||||
const timestampRegex = /LOG:\s(\d*:\d*:\d*)\s---/;
|
||||
|
||||
const singleMinFpsRegex = /Single min\. FPS for (.*):\s(\d*.\d*)"/; // group1 = entity name, group2 = value
|
||||
|
||||
const singleAvgFpsRegex = /Single avg\. FPS for (.*):\s(\d*.\d*)"/; // group1 = entity name, group2 = value
|
||||
|
||||
const minFpsRegex = /Min\. FPS for (.*):\s\[(.*)\]"/; // group1 = entity name, group2 = comma separated values
|
||||
|
||||
const avgFpsRegex = /Avg\. FPS for (.*):\s\[(.*)\]"/; // group1 = entity name, group2 = comma separated values
|
||||
|
||||
const parseWarLog = (lineArray, war) => {
|
||||
let flagBlufor = true;
|
||||
|
@ -48,6 +56,7 @@ const parseWarLog = (lineArray, war) => {
|
|||
transport: [],
|
||||
players: [],
|
||||
playerCount: [],
|
||||
serverFps: [],
|
||||
};
|
||||
|
||||
const VEHICLE_BLACKLIST = [
|
||||
|
@ -265,6 +274,43 @@ const parseWarLog = (lineArray, war) => {
|
|||
countBlufor: countBlufor,
|
||||
countOpfor: countOpfor,
|
||||
});
|
||||
} else if (line.includes('(FPS)')) {
|
||||
stats.clean.push(line);
|
||||
|
||||
const updateServerFpsLogEntry = (entityName, addKey, addValue) => {
|
||||
const idx = stats.serverFps.findIndex((entry) => entry.entityName === entityName);
|
||||
if (idx === -1) {
|
||||
stats.serverFps.push({
|
||||
war: war.id,
|
||||
entityName: entityName,
|
||||
[addKey]: addValue,
|
||||
});
|
||||
return;
|
||||
}
|
||||
const entity = stats.serverFps[idx];
|
||||
entity[addKey] = addValue;
|
||||
stats.serverFps[idx] = entity;
|
||||
};
|
||||
|
||||
const singleMinMatch = singleMinFpsRegex.exec(line);
|
||||
if (singleMinMatch) {
|
||||
updateServerFpsLogEntry(singleMinMatch[1], 'singleMinFps', singleMinMatch[2]);
|
||||
} else {
|
||||
const singleAvgMatch = singleAvgFpsRegex.exec(line);
|
||||
if (singleAvgMatch) {
|
||||
updateServerFpsLogEntry(singleAvgMatch[1], 'singleAvgFps', singleAvgMatch[2]);
|
||||
} else {
|
||||
const minCollectionMatch = minFpsRegex.exec(line);
|
||||
if (minCollectionMatch) {
|
||||
updateServerFpsLogEntry(minCollectionMatch[1], 'minFps', minCollectionMatch[2].split(','));
|
||||
} else {
|
||||
const avgCollectionMatch = avgFpsRegex.exec(line);
|
||||
if (avgCollectionMatch) {
|
||||
updateServerFpsLogEntry(avgCollectionMatch[1], 'avgFps', avgCollectionMatch[2].split(','));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (line.includes('(Fraktionsuebersicht)') || line.includes('Fraktionsübersicht')) {
|
||||
/**
|
||||
* PLAYERS
|
||||
|
|
Loading…
Reference in New Issue