Add bar chart per player fps visualization (CC-80)

pull/51/head
HardiReady 2019-02-09 21:55:13 +01:00
parent 03073f5436
commit 9c6f74c14f
7 changed files with 123 additions and 50 deletions

View File

@ -4,6 +4,9 @@
const express = require('express');
const async = require('async');
// HTTP status codes by name
const codes = require('./http-codes');
const routerHandling = require('../middleware/router-handling');
// Mongoose Model using mongoDB
@ -16,6 +19,7 @@ const LogTransportModel = require('../models/logs/transport');
const LogFlagModel = require('../models/logs/flag');
const LogPointsModel = require('../models/logs/points');
const LogPlayerCountModel = require('../models/logs/player-count');
const LogServerFpsModel = require('../models/logs/server-fps');
const logsRouter = new express.Router();
@ -24,7 +28,7 @@ const processLogRequest = (model, filter, res, next) => {
if (err) return next(err);
if (!log || log.length === 0) {
const err = new Error('No logs found');
err.status = require('./http-codes').notfound;
err.status = codes.notfound;
return next(err);
}
res.locals.items = log;
@ -154,6 +158,24 @@ logsRouter.route('/:warId/points')
routerHandling.httpMethodNotAllowed
);
logsRouter.route('/:warId/performance')
.get((req, res, next) => {
const filter = {war: req.params.warId};
LogServerFpsModel.find(filter, (err, items) => {
if (err) return next(err);
if (!items) {
const err = new Error('No logs found');
err.status = codes.notfound;
return next(err);
}
res.locals.items = items;
next();
});
})
.all(
routerHandling.httpMethodNotAllowed
);
logsRouter.use(routerHandling.emptyResponse);
module.exports = logsRouter;

View File

@ -35,6 +35,7 @@ export interface Player {
revive?: number;
respawn?: number;
flagTouch?: number;
performance?: string;
}
export interface CampaignPlayer {

View File

@ -68,4 +68,8 @@ export class LogsService {
params.append('defend', defendOnly ? 'true' : '');
return this.httpGateway.get(this.config.apiLogsPath + '/' + warId + '/flag', params);
}
getPerformanceLogs(warId: string) {
return this.httpGateway.get(this.config.apiLogsPath + '/' + warId + '/performance');
}
}

View File

@ -10,8 +10,8 @@
</mat-button-toggle-group>
<div class="chart-container">
<ngx-charts-line-chart
[results]="lineChartData"
<ngx-charts-bar-vertical
[results]="barChartData"
[gradient]="gradient"
[xAxis]="xAxis"
[yAxis]="yAxis"
@ -19,10 +19,26 @@
[legendTitle]="legendTitle"
[showXAxisLabel]="showXAxisLabel"
[showYAxisLabel]="showYAxisLabel"
[yAxisLabel]="lineChartLabel"
[autoScale]="autoscale"
[timeline]="timeline"
[yAxisLabel]="barChartLabel"
[barPadding]="2"
[roundDomains]="roundDomains">
</ngx-charts-line-chart>
</ngx-charts-bar-vertical>
</div>
<!--<div class="chart-container">-->
<!--<ngx-charts-line-chart-->
<!--[results]="barChartData"-->
<!--[gradient]="gradient"-->
<!--[xAxis]="xAxis"-->
<!--[yAxis]="yAxis"-->
<!--[legend]="legend"-->
<!--[legendTitle]="legendTitle"-->
<!--[showXAxisLabel]="showXAxisLabel"-->
<!--[showYAxisLabel]="showYAxisLabel"-->
<!--[yAxisLabel]="barChartLabel"-->
<!--[autoScale]="autoscale"-->
<!--[timeline]="timeline"-->
<!--[roundDomains]="roundDomains">-->
<!--</ngx-charts-line-chart>-->
<!--</div>-->
</div>

View File

@ -1,5 +1,4 @@
import {Component, ElementRef, Input, OnChanges, OnInit, SimpleChanges, ViewChild} from '@angular/core';
import {ChartUtils} from '../../../utils/chart-utils';
import {War} from '../../../models/model-interfaces';
import {TranslateService} from '@ngx-translate/core';
@ -19,21 +18,19 @@ export class ServerStatsComponent implements OnInit, OnChanges {
startDateObj: Date;
initialized: any;
public activeChartSelect: string;
barChartData: any[] = [];
lineChartData: any[] = [];
tmpPointData;
tmpBudgetData;
tmpKillData;
tmpFrienlyFireData;
tmpVehicleData;
tmpTransportData;
tmpReviveData;
tmpStabilizeData;
tmpFlagCaptureData;
showBarChart = true;
tmpSingleAvg;
tmpSingleMin;
tmpAvgTimeline;
tmpMinTimeline;
tmpServerTimeline;
readonly labels = {
singleAvg: 'stats.performance.select.single.avg',
@ -45,6 +42,7 @@ export class ServerStatsComponent implements OnInit, OnChanges {
readonly labelsAsString = Object.keys(this.labels)
.map((key) => this.labels[key]);
barChartLabel: string;
lineChartLabel: string;
gradient = false;
@ -62,21 +60,14 @@ export class ServerStatsComponent implements OnInit, OnChanges {
}
ngOnInit() {
this.setLineChartLabel(this.labels.singleAvg);
this.setBarChartLabel(this.labels.singleAvg);
}
ngOnChanges(changes: SimpleChanges) {
if (changes.war || changes.performanceData) {
this.initialized = {
budget: false,
kill: false,
revive: false,
transport: false,
flag: false
};
Object.assign(this, [this.lineChartData]);
this.initializeChartData();
Object.assign(this, [this.barChartData]);
this.activeChartSelect = this.labels.singleAvg;
this.startDateObj = new Date(this.war.date);
this.startDateObj.setHours(0);
this.startDateObj.setMinutes(1);
@ -85,26 +76,49 @@ export class ServerStatsComponent implements OnInit, OnChanges {
selectChart(newSelection) {
this.activeChartSelect = newSelection;
if (this.activeChartSelect !== this.labels.serverFps) {
this.showBarChart = true;
this.setBarChartLabel(this.activeChartSelect);
switch (this.activeChartSelect) {
case this.labels.singleAvg:
this.barChartData = this.tmpSingleAvg;
break;
case this.labels.singleMin:
this.barChartData = this.tmpSingleMin;
break;
}
} else {
this.showBarChart = false;
this.setLineChartLabel(this.activeChartSelect);
console.log('############### apply data ##################');
switch (this.activeChartSelect) {
case this.labels.avgTimeline:
this.lineChartData = this.tmpAvgTimeline;
break;
case this.labels.minTimeline:
this.lineChartData = this.tmpMinTimeline;
break;
case this.labels.serverFps:
this.lineChartData = this.tmpServerTimeline;
}
}
}
addFinalTimeData(tmpCollection) {
const endDate = new Date(this.war.endDate);
if (tmpCollection === this.tmpBudgetData) {
this.tmpBudgetData[0].series.push(ChartUtils.getSeriesEntry(endDate, this.war.endBudgetBlufor));
this.tmpBudgetData[1].series.push(ChartUtils.getSeriesEntry(endDate, this.war.endBudgetOpfor));
} else {
for (let j = 0; j < tmpCollection.length; j++) {
// mayBe check is needed for logs that are simply not existent in older wars, i.e. vehicleKills
const maybeLast = tmpCollection[j].series[tmpCollection[j].series.length - 1];
if (maybeLast && maybeLast.name < endDate) {
tmpCollection[j].series.push(
ChartUtils.getSeriesEntry(endDate, tmpCollection[j].series[tmpCollection[j].series.length - 1].value)
);
}
}
}
initializeChartData() {
this.tmpSingleAvg = [];
this.tmpSingleMin = [];
this.performanceData.forEach((entry) => {
this.tmpSingleAvg.push({
name: entry.entityName,
value: entry.singleAvgFps
});
this.tmpSingleMin.push({
name: entry.entityName,
value: entry.singleMinFps
});
});
this.tmpSingleAvg.sort((a, b) => a.value - b.value);
this.tmpSingleMin.sort((a, b) => a.value - b.value);
this.barChartData = this.tmpSingleAvg;
}
setLineChartLabel(i18n: string) {
@ -112,4 +126,10 @@ export class ServerStatsComponent implements OnInit, OnChanges {
this.lineChartLabel = translated;
});
}
setBarChartLabel(i18n: string) {
this.translate.get(i18n).subscribe((translated) => {
this.barChartLabel = translated;
});
}
}

View File

@ -48,7 +48,7 @@
{{'stats.scoreboard.tab.player' | translate}}
</a>
</li>
<li class="nav-item" [ngClass]="{active :tab === 3}" (click)="switchTab(3)">
<li class="nav-item" [ngClass]="{active :tab === 3}" (click)="switchTab(3)" *ngIf="war && war.players[0].performance">
<a class="nav-link">
<mat-icon svgIcon="stats-performance" class="mat-icon-stats-performance"></mat-icon>
{{'stats.scoreboard.tab.performance' | translate}}
@ -109,7 +109,7 @@
<cc-server-statistics
*ngIf="tab === 3"
[war]="war"
[performanceData]="[]">
[performanceData]="performanceData">
</cc-server-statistics>
</div>

View File

@ -23,14 +23,18 @@ export class WarHeaderComponent implements OnInit {
logData;
fractionStatsInitialized: boolean;
performanceData;
performanceStatsInitialized: boolean;
singlePlayerView: number;
playerDetailName: string;
tab: number;
fractionStatsInitialized: boolean;
fractionFilterSelected: string;
playerChart: any[] = [];
@ -70,6 +74,12 @@ export class WarHeaderComponent implements OnInit {
this.fractionStatsInitialized = true;
});
}
if (index === 3 && !this.performanceStatsInitialized) {
this.logsService.getPerformanceLogs(this.war._id).subscribe(log => {
this.performanceData = log;
this.performanceStatsInitialized = true;
});
}
}
/**