Add war-log upload endpoint and processing
parent
2fa616570c
commit
84b19310b6
|
@ -11,5 +11,6 @@ module.exports = {
|
||||||
squads: '/squads',
|
squads: '/squads',
|
||||||
users: '/users',
|
users: '/users',
|
||||||
account: '/account',
|
account: '/account',
|
||||||
request: '/request'
|
request: '/request',
|
||||||
|
wars: '/wars'
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const mongoose = require('mongoose');
|
||||||
|
const Schema = mongoose.Schema;
|
||||||
|
|
||||||
|
const PlayerSchema = new Schema({
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
fraction: {
|
||||||
|
type: String,
|
||||||
|
enum: ['BLUFOR', 'OPFOR'],
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
warId: {
|
||||||
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
|
ref: 'War',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
kill: {
|
||||||
|
type: Number,
|
||||||
|
get: v => Math.round(v),
|
||||||
|
set: v => Math.round(v),
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
death: {
|
||||||
|
type: Number,
|
||||||
|
get: v => Math.round(v),
|
||||||
|
set: v => Math.round(v),
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
friendlyFire: {
|
||||||
|
type: Number,
|
||||||
|
get: v => Math.round(v),
|
||||||
|
set: v => Math.round(v),
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
respawn: {
|
||||||
|
type: Number,
|
||||||
|
get: v => Math.round(v),
|
||||||
|
set: v => Math.round(v),
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
flagTouch: {
|
||||||
|
type: Number,
|
||||||
|
get: v => Math.round(v),
|
||||||
|
set: v => Math.round(v),
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
collection: 'player',
|
||||||
|
timestamps: {createdAt: 'timestamp'}
|
||||||
|
});
|
||||||
|
// optional more indices
|
||||||
|
PlayerSchema.index({timestamp: 1});
|
||||||
|
|
||||||
|
module.exports = mongoose.model('Player', PlayerSchema);
|
|
@ -0,0 +1,35 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const mongoose = require('mongoose');
|
||||||
|
const Schema = mongoose.Schema;
|
||||||
|
|
||||||
|
const WarSchema = new Schema({
|
||||||
|
date: {
|
||||||
|
type: Date,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
ptBlufor: {
|
||||||
|
type: Number,
|
||||||
|
get: v => Math.round(v),
|
||||||
|
set: v => Math.round(v),
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
ptOpfor: {
|
||||||
|
type: Number,
|
||||||
|
get: v => Math.round(v),
|
||||||
|
set: v => Math.round(v),
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
bestPlayerId: {
|
||||||
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
|
ref: 'Player',
|
||||||
|
default: null
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
collection: 'war',
|
||||||
|
timestamps: {createdAt: 'timestamp'}
|
||||||
|
});
|
||||||
|
// optional more indices
|
||||||
|
WarSchema.index({timestamp: 1});
|
||||||
|
|
||||||
|
module.exports = mongoose.model('War', WarSchema);
|
File diff suppressed because it is too large
Load Diff
|
@ -25,7 +25,8 @@
|
||||||
"jimp": "^0.2.27",
|
"jimp": "^0.2.27",
|
||||||
"jsonwebtoken": "^7.4.0",
|
"jsonwebtoken": "^7.4.0",
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
"mongoose": "^4.3.0",
|
"mkdirp": "^0.5.1",
|
||||||
|
"mongoose": "^4.11.1",
|
||||||
"morgan": "~1.6.1",
|
"morgan": "~1.6.1",
|
||||||
"multer": "^1.3.0",
|
"multer": "^1.3.0",
|
||||||
"node-sha1": "^1.0.1",
|
"node-sha1": "^1.0.1",
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// modules
|
||||||
|
const fs = require('fs');
|
||||||
|
const mkdirp = require("mkdirp");
|
||||||
|
const {exec} = require('child_process');
|
||||||
|
const express = require('express');
|
||||||
|
const multer = require('multer');
|
||||||
|
const storage = multer.memoryStorage();
|
||||||
|
const upload = multer({storage: storage});
|
||||||
|
const logger = require('debug')('cc:squads');
|
||||||
|
|
||||||
|
// HTTP status codes by name
|
||||||
|
const codes = require('./http-codes');
|
||||||
|
|
||||||
|
const apiAuthenticationMiddleware = require('../middleware/auth-middleware');
|
||||||
|
// const checkMT = require('../middleware/permission-check').checkMT();
|
||||||
|
const routerHandling = require('../middleware/router-handling');
|
||||||
|
|
||||||
|
// Mongoose Model using mongoDB
|
||||||
|
const WarModel = require('../models/war');
|
||||||
|
|
||||||
|
const wars = express.Router();
|
||||||
|
|
||||||
|
// routes **********************
|
||||||
|
wars.route('/')
|
||||||
|
// .get((req, res, next) => {
|
||||||
|
// const filter = {};
|
||||||
|
// WarModel.find(filter, {}, {sort: {date: 'asc'}}, (err, items) => {
|
||||||
|
// if (err) {
|
||||||
|
// err.status = codes.servererror;
|
||||||
|
// return next(err);
|
||||||
|
// }
|
||||||
|
// if (items) {
|
||||||
|
// res.locals.items = items;
|
||||||
|
// } else {
|
||||||
|
// res.locals.items = [];
|
||||||
|
// }
|
||||||
|
// res.locals.processed = true;
|
||||||
|
// next();
|
||||||
|
// });
|
||||||
|
// })
|
||||||
|
|
||||||
|
.post(upload.single('log'), (req, res, next) => {
|
||||||
|
const war = new WarModel(req.body);
|
||||||
|
// timestamp and default are set automatically by Mongoose Schema Validation
|
||||||
|
if (req.file) {
|
||||||
|
const timestamp = new Date();
|
||||||
|
const uploadDate = timestamp.toISOString().slice(0, 10) + '_' + timestamp.toTimeString().slice(0, 8)
|
||||||
|
const folderName = __dirname + '/../resource/logs/' + uploadDate;
|
||||||
|
mkdirp(folderName, function (err) {
|
||||||
|
if (err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
fs.appendFile(folderName + '/war.log', new Buffer(req.file.buffer), (err) => {
|
||||||
|
if (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
exec(__dirname + '/../war-parser/run.sh ' + folderName + ' | tee resource/logs/' + uploadDate + '/score.log' , (error, stdout, stderr) => {
|
||||||
|
console.log("log")
|
||||||
|
if (error) {
|
||||||
|
return next(error);
|
||||||
|
}
|
||||||
|
console.log(`stdout: ${stdout}`);
|
||||||
|
console.log(`stderr: ${stderr}`);
|
||||||
|
res.locals.items={};
|
||||||
|
return next();
|
||||||
|
});
|
||||||
|
|
||||||
|
// exec(__dirname + '/../war-parser/clean.sh ' + folderName + ' | tee resource/logs/' + uploadDate + '/clean.log' , (error) => {
|
||||||
|
// if (error) {
|
||||||
|
// return next(error);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// });
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// war.save((err) => {
|
||||||
|
// if (err) {
|
||||||
|
// err.status = codes.wrongrequest;
|
||||||
|
// err.message += ' in fields: ' + Object.getOwnPropertyNames(err.errors);
|
||||||
|
// return next(err);
|
||||||
|
// }
|
||||||
|
// res.status(codes.created);
|
||||||
|
// res.locals.items = war;
|
||||||
|
// fs.appendFile(__dirname + '/../resource/squad/' + war.id + '.png', new Buffer(req.file.buffer), (err) => {
|
||||||
|
// if (err) next(err);
|
||||||
|
// });
|
||||||
|
// next();
|
||||||
|
// })
|
||||||
|
} else {
|
||||||
|
const err = new Error('no Logfile provided');
|
||||||
|
err.status = codes.wrongmediasend;
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
.all(
|
||||||
|
routerHandling.httpMethodNotAllowed
|
||||||
|
);
|
||||||
|
//
|
||||||
|
// wars.route('/:id')
|
||||||
|
// .get((req, res, next) => {
|
||||||
|
// WarModel.findById(req.params.id, (err, item) => {
|
||||||
|
// if (err) {
|
||||||
|
// err.status = codes.servererror;
|
||||||
|
// return next(err);
|
||||||
|
// }
|
||||||
|
// else if (!item) {
|
||||||
|
// err = new Error("item not found");
|
||||||
|
// err.status = codes.notfound;
|
||||||
|
// return next(err);
|
||||||
|
// }
|
||||||
|
// res.locals.items = item;
|
||||||
|
// next();
|
||||||
|
// });
|
||||||
|
// })
|
||||||
|
//
|
||||||
|
// .delete(apiAuthenticationMiddleware, checkHl, (req, res, next) => {
|
||||||
|
// WarModel.findByIdAndRemove(req.params.id, (err, item) => {
|
||||||
|
// if (err) {
|
||||||
|
// err.status = codes.wrongrequest;
|
||||||
|
// }
|
||||||
|
// else if (!item) {
|
||||||
|
// err = new Error("item not found");
|
||||||
|
// err.status = codes.notfound;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // delete graphic
|
||||||
|
// fs.unlink(__dirname + '/../resource/squad/' + req.params.id + '.png', (err) => {
|
||||||
|
// if (err) next(err);
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// // we don't set res.locals.items and thus it will send a 204 (no content) at the end. see last handler user.use(..)
|
||||||
|
// res.locals.processed = true;
|
||||||
|
// next(err); // this works because err is in normal case undefined and that is the same as no parameter
|
||||||
|
// });
|
||||||
|
// })
|
||||||
|
//
|
||||||
|
// .all(
|
||||||
|
// routerHandling.httpMethodNotAllowed
|
||||||
|
// );
|
||||||
|
|
||||||
|
// this middleware function can be used, if you like or remove it
|
||||||
|
// it looks for object(s) in res.locals.items and if they exist, they are send to the client as json
|
||||||
|
wars.use(routerHandling.emptyResponse);
|
||||||
|
|
||||||
|
module.exports = wars;
|
|
@ -31,6 +31,7 @@ const awardingRouter = require('./routes/awardings');
|
||||||
const requestRouter = require('./routes/request');
|
const requestRouter = require('./routes/request');
|
||||||
const signatureRouter = require('./routes/signatures');
|
const signatureRouter = require('./routes/signatures');
|
||||||
const commandRouter = require('./routes/command');
|
const commandRouter = require('./routes/command');
|
||||||
|
const warRouter = require('./routes/war');
|
||||||
|
|
||||||
// Configuration ***********************************
|
// Configuration ***********************************
|
||||||
// mongoose promise setup
|
// mongoose promise setup
|
||||||
|
@ -75,6 +76,7 @@ app.use(urls.ranks, rankRouter);
|
||||||
app.use(urls.decorations, decorationRouter);
|
app.use(urls.decorations, decorationRouter);
|
||||||
app.use(urls.request, requestRouter);
|
app.use(urls.request, requestRouter);
|
||||||
app.use(urls.awards, awardingRouter);
|
app.use(urls.awards, awardingRouter);
|
||||||
|
app.use(urls.wars, warRouter);
|
||||||
app.use(urls.command, apiAuthenticationMiddleware, checkAdmin, commandRouter);
|
app.use(urls.command, apiAuthenticationMiddleware, checkAdmin, commandRouter);
|
||||||
app.use(urls.account, apiAuthenticationMiddleware, checkAdmin, accountRouter);
|
app.use(urls.account, apiAuthenticationMiddleware, checkAdmin, accountRouter);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
"use strict"
|
"use strict";
|
||||||
|
|
||||||
// modules used for graphic manipulation
|
// modules used for graphic manipulation
|
||||||
const jimp = require('jimp');
|
const jimp = require('jimp');
|
||||||
|
|
|
@ -1,20 +1,15 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
FILE="$1"
|
FILE="$1/war.log"
|
||||||
FILTER=("Budget" "Mission" "Abschuss" "Respawn" "Punkte")
|
|
||||||
|
|
||||||
pat=$(echo ${FILTER[@]}|tr " " "|")
|
while IFS='' read -r line || [[ -n "$line" ]]; do
|
||||||
|
case "$line" in
|
||||||
|
*"Budget"* | *"Mission"* | *"Abschuss"* | *"Respawn"* | *"Punkte"*)
|
||||||
while IFS= read -r line; do
|
echo $line;
|
||||||
if [[ $line =~ [^[:space:]] ]]; then
|
|
||||||
RES="$(grep -Ew "$pat" <<< "$line")"
|
|
||||||
if [[ ${RES} =~ [^[:space:]] ]]; then
|
|
||||||
echo ${RES}
|
|
||||||
echo ""
|
echo ""
|
||||||
fi
|
;;
|
||||||
fi
|
esac
|
||||||
done < <(cat ${FILE} )
|
done < ${FILE}
|
||||||
|
|
||||||
# Add OPT Scoreboard
|
# Add OPT Scoreboard
|
||||||
while IFS= read -r line; do
|
while IFS= read -r line; do
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
createScoreboardHeader() {
|
|
||||||
printf "%25s %8s %8s %8s %8s %8s\n" "Name" "Kill" "FF" "Death" "Respawn"
|
|
||||||
echo "---------------------------------------------------------------------------"
|
|
||||||
}
|
|
||||||
|
|
||||||
createScoreboard() {
|
createScoreboard() {
|
||||||
NAME="$1"
|
NAME="$1"
|
||||||
FILE="$2"
|
FILE="$2"
|
||||||
|
@ -34,14 +29,16 @@ createScoreboard() {
|
||||||
esac
|
esac
|
||||||
done < <(grep -- "${ESC_NAME}" ${FILE})
|
done < <(grep -- "${ESC_NAME}" ${FILE})
|
||||||
|
|
||||||
#echo {\"name\":\"$NAME\", \"kill\":${KILL}, \"ff\":${FF}, \"death\":${DEATH}, \"respawn\":${RESPAWN}},
|
printf "\t{\"name\":\"$NAME\", \"kill\":${KILL}, \"ff\":${FF}, \"death\":${DEATH}, \"respawn\":${RESPAWN}}"
|
||||||
if [[ $NAME =~ [^[:space:]] ]]; then
|
if [[ -z ${3} ]]; then
|
||||||
printf "%25s %8s %8s %8s %8s %8s\n" "$NAME" $KILL $FF $DEATH $RESPAWN
|
printf ",\n"
|
||||||
|
else
|
||||||
|
printf "\n"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FILE="$1"
|
FILE="$1/war.log"
|
||||||
PLAYERS=()
|
PLAYERS=()
|
||||||
|
|
||||||
while IFS='' read -r line || [[ -n "$line" ]]; do
|
while IFS='' read -r line || [[ -n "$line" ]]; do
|
||||||
|
@ -68,10 +65,13 @@ while IFS='' read -r line || [[ -n "$line" ]]; do
|
||||||
fi
|
fi
|
||||||
done < ${FILE}
|
done < ${FILE}
|
||||||
|
|
||||||
createScoreboardHeader
|
echo "["
|
||||||
|
|
||||||
for i in "${PLAYERS[@]}"
|
for ((i=0; i<${#PLAYERS[*]}; i++));
|
||||||
do
|
do
|
||||||
:
|
if [[ "$((i+1))" -eq "${#PLAYERS[*]}" ]]; then
|
||||||
createScoreboard "$i" ${FILE}
|
last="true"
|
||||||
|
fi
|
||||||
|
createScoreboard "${PLAYERS[i]}" ${FILE} ${last}
|
||||||
done
|
done
|
||||||
|
echo "]"
|
||||||
|
|
Loading…
Reference in New Issue