diff --git a/api/apib/statistics/campaigns.apib b/api/apib/statistics/campaigns.apib index 2b4cc8f..95c9edf 100644 --- a/api/apib/statistics/campaigns.apib +++ b/api/apib/statistics/campaigns.apib @@ -2,7 +2,6 @@ Get all campaigns information - + Response 200 (application/json; charset=utf-8) + Attributes (array[Campaign], fixed-type) @@ -17,6 +16,18 @@ Get single campaign information + Response 200 (application/json; charset=utf-8) + Attributes (Campaign, fixed-type) + +### Get Campaign Containing Specific War [GET /campaigns/with/war/{warId}] + +Get a single campaign, containing a specific war + ++ Parameters + + warId: `5abf65ae3fc5fa349ffd5ca3` (string, required) - unique id of war that has to be part of campaign + ++ Response 200 (application/json; charset=utf-8) + + + Attributes (Campaign, fixed-type) + ### Create Campaign [POST /campaigns] diff --git a/api/apib/statistics/wars.apib b/api/apib/statistics/wars.apib index c370a9c..9299baf 100644 --- a/api/apib/statistics/wars.apib +++ b/api/apib/statistics/wars.apib @@ -1,10 +1,13 @@ -### List Wars [GET /wars] +### List Wars [GET /wars{?campaignId}] -List all wars, subordinate to their campaign +List all wars + ++ Parameters + + campaignId: `5abd55ea9e30a76bfef747d6` (string, optional) - show only wars from campaign with this id + Response 200 (application/json; charset=utf-8) - + Attributes (array[WarCampaign], fixed-type) + + Attributes (array[War], fixed-type) ### Get War [GET /wars/{id}] diff --git a/api/routes/campaigns.js b/api/routes/campaigns.js index a9ae52f..e292624 100644 --- a/api/routes/campaigns.js +++ b/api/routes/campaigns.js @@ -63,6 +63,21 @@ campaigns.route('/') routerHandling.httpMethodNotAllowed ); +campaigns.route('/with/war/:id') + .get((req, res, next) => { + WarModel.findById(req.params.id, (err, item) => { + if (err) { + err.status = codes.servererror; + return next(err); + } + return genericGetById({params: {id: item.campaign}}, res, next, CampaignModel); + }); + }) + + .all( + routerHandling.httpMethodNotAllowed + ); + campaigns.route('/:id') .get(idValidator, (req, res, next) => { return genericGetById(req, res, next, CampaignModel); diff --git a/api/routes/users.js b/api/routes/users.js index 30ffe94..6145877 100644 --- a/api/routes/users.js +++ b/api/routes/users.js @@ -57,7 +57,7 @@ users.route('/') return next(); } - UserModel.count(dbFilter, (err, totalCount) => { + UserModel.countDocuments(dbFilter, (err, totalCount) => { res.set('x-total-count', totalCount); res.locals.items = users; res.locals.processed = true; diff --git a/api/routes/wars.js b/api/routes/wars.js index cf57b6a..692e37f 100644 --- a/api/routes/wars.js +++ b/api/routes/wars.js @@ -23,7 +23,6 @@ const resourceLocation = require('../middleware/resource-location').resourceLoca const parseWarLog = require('../tools/log-parse-tool'); // Mongoose Model using mongoDB -const CampaignModel = require('../models/campaign'); const WarModel = require('../models/war'); const PlayerModel = require('../models/player'); const LogKillModel = require('../models/logs/kill'); @@ -43,36 +42,18 @@ const wars = new express.Router(); // routes ********************** wars.route('/') .get((req, res, next) => { - let result = []; - CampaignModel.find({}, {}, {sort: {timestamp: 'desc'}}, (err, campaigns) => { + const filter = {}; + if (req.query.campaignId) { + filter.campaign = req.query.campaignId; + } + WarModel.find(filter, {}, {sort: {date: 'desc'}}, (err, wars) => { if (err) { err.status = codes.servererror; return next(err); } - if (campaigns) { - WarModel.find({}, {}, {sort: {date: 'desc'}}, (err, wars) => { - if (err) { - err.status = codes.servererror; - return next(err); - } - if (wars) { - campaigns.forEach((campaign) => { - let entry = {_id: campaign._id, title: campaign.title, wars: []}; - wars.forEach((war) => { - if (String(campaign._id) === String(war.campaign)) { - entry.wars.push(war); - } - }); - result.push(entry); - }); - res.locals.items = result; - } - res.locals.processed = true; - next(); - } - ) - ; - } + res.locals.items = wars; + res.locals.processed = true; + next(); }); }) diff --git a/api/server.js b/api/server.js index 64009a0..684ffe2 100644 --- a/api/server.js +++ b/api/server.js @@ -63,6 +63,7 @@ const corsOptions = { methods: ['GET'], optionsSuccessStatus: 200, }; + app.use(cors(corsOptions)); app.use(favicon(path.join(__dirname + '/..', 'public', 'favicon.ico'))); @@ -146,25 +147,40 @@ if (process.env.NODE_ENV === config.test.unit.env || process.env.NODE_ENV === co }); } else { mongoose.connect(config.database.uri + config.database.db, {useNewUrlParser: true}).then((db) => { + let cronWorkerPID; if (cluster.isMaster) { // Fork workers for (let i = 0; i < numWorkers; i++) { - cluster.fork(); + if (i === 0) { + const spawnedWorker = cluster.fork({START_CRON: true}); + cronWorkerPID = spawnedWorker.process.pid; + } else { + cluster.fork(); + } } logger(`Master ${process.pid} is running. Forking ${numWorkers} workers`); // Check if worker id is died cluster.on('exit', (worker, code, signal) => { logger(`worker ${worker.process.pid} died`); + if (worker.process.pid === cronWorkerPID) { + const spawnedWorker = cluster.fork({START_CRON: true}); + cronWorkerPID = spawnedWorker.process.pid; + } else { + cluster.fork(); + } }); } else { app.listen(config.port, (err) => { - if (err !== undefined) { + if (err) { error(`Error on startup ${err}`); } else { logger(`Worker ${process.pid} started. Listening on port ${config.port}`); - signatureCronJob.start(); - backupCronJob.start(); + if (process.env.START_CRON) { + logger(`Attaching cronJobs to cluster worker ${process.pid}`); + signatureCronJob.start(); + backupCronJob.start(); + } } }); } diff --git a/api/tools/log-parse-tool.js b/api/tools/log-parse-tool.js index 83a72c0..15a066b 100644 --- a/api/tools/log-parse-tool.js +++ b/api/tools/log-parse-tool.js @@ -24,6 +24,9 @@ const vehicleRegex = /(vehicle:\s(.*?)\))/; const categoryRegex = /(category:\s(.*?)\))/; const parseWarLog = (lineArray, war) => { + let flagBlufor = true; + let flagOpfor = true; + const NAME_TOO_LONG_ERROR = 'Error: ENAMETOOLONG: name too long, open \''; const stats = { @@ -164,18 +167,29 @@ const parseWarLog = (lineArray, war) => { /** * FLAG */ - stats.clean.push(line); - const playerName = line.substring(line.lastIndexOf('rt von ') + 7).slice(0, -1); const flagFraction = line.includes('NATO Flagge') ? 'BLUFOR' : 'OPFOR'; const capture = !!line.includes('Flagge erobert'); - stats.flag.push({ - war: war._id, - time: getFullTimeDate(war.date, line.split(WHITESPACE)[5]), - player: playerName, - flagFraction: flagFraction, - capture: capture, - }); + if ((flagFraction === 'BLUFOR' && ((capture && flagBlufor) || (!capture && !flagBlufor))) || + (flagFraction === 'OPFOR' && ((capture && flagOpfor) || (!capture && !flagOpfor)))) { + stats.clean.push(line); + + const playerName = line.substring(line.lastIndexOf('rt von ') + 7).slice(0, -1); + + if (flagFraction === 'BLUFOR') { + flagBlufor = !capture; + } else if (flagFraction === 'OPFOR') { + flagOpfor = !capture; + } + + stats.flag.push({ + war: war._id, + time: getFullTimeDate(war.date, line.split(WHITESPACE)[5]), + player: playerName, + flagFraction: flagFraction, + capture: capture, + }); + } } else if (line.includes('(Punkte)')) { /** * POINTS diff --git a/docs/infra/codestyle/cc-intellij-idea-javascript-typescript-style.xml b/docs/infra/codestyle/cc-intellij-idea-javascript-typescript-style.xml index 8128b6f..c7999c0 100644 --- a/docs/infra/codestyle/cc-intellij-idea-javascript-typescript-style.xml +++ b/docs/infra/codestyle/cc-intellij-idea-javascript-typescript-style.xml @@ -11,7 +11,6 @@