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

View File

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

View File

@ -68,4 +68,8 @@ export class LogsService {
params.append('defend', defendOnly ? 'true' : ''); params.append('defend', defendOnly ? 'true' : '');
return this.httpGateway.get(this.config.apiLogsPath + '/' + warId + '/flag', params); 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> </mat-button-toggle-group>
<div class="chart-container"> <div class="chart-container">
<ngx-charts-line-chart <ngx-charts-bar-vertical
[results]="lineChartData" [results]="barChartData"
[gradient]="gradient" [gradient]="gradient"
[xAxis]="xAxis" [xAxis]="xAxis"
[yAxis]="yAxis" [yAxis]="yAxis"
@ -19,10 +19,26 @@
[legendTitle]="legendTitle" [legendTitle]="legendTitle"
[showXAxisLabel]="showXAxisLabel" [showXAxisLabel]="showXAxisLabel"
[showYAxisLabel]="showYAxisLabel" [showYAxisLabel]="showYAxisLabel"
[yAxisLabel]="lineChartLabel" [yAxisLabel]="barChartLabel"
[autoScale]="autoscale" [barPadding]="2"
[timeline]="timeline"
[roundDomains]="roundDomains"> [roundDomains]="roundDomains">
</ngx-charts-line-chart> </ngx-charts-bar-vertical>
</div> </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> </div>

View File

@ -1,5 +1,4 @@
import {Component, ElementRef, Input, OnChanges, OnInit, SimpleChanges, ViewChild} from '@angular/core'; import {Component, ElementRef, Input, OnChanges, OnInit, SimpleChanges, ViewChild} from '@angular/core';
import {ChartUtils} from '../../../utils/chart-utils';
import {War} from '../../../models/model-interfaces'; import {War} from '../../../models/model-interfaces';
import {TranslateService} from '@ngx-translate/core'; import {TranslateService} from '@ngx-translate/core';
@ -19,21 +18,19 @@ export class ServerStatsComponent implements OnInit, OnChanges {
startDateObj: Date; startDateObj: Date;
initialized: any;
public activeChartSelect: string; public activeChartSelect: string;
barChartData: any[] = [];
lineChartData: any[] = []; lineChartData: any[] = [];
tmpPointData; showBarChart = true;
tmpBudgetData;
tmpKillData; tmpSingleAvg;
tmpFrienlyFireData; tmpSingleMin;
tmpVehicleData; tmpAvgTimeline;
tmpTransportData; tmpMinTimeline;
tmpReviveData; tmpServerTimeline;
tmpStabilizeData;
tmpFlagCaptureData;
readonly labels = { readonly labels = {
singleAvg: 'stats.performance.select.single.avg', singleAvg: 'stats.performance.select.single.avg',
@ -45,6 +42,7 @@ export class ServerStatsComponent implements OnInit, OnChanges {
readonly labelsAsString = Object.keys(this.labels) readonly labelsAsString = Object.keys(this.labels)
.map((key) => this.labels[key]); .map((key) => this.labels[key]);
barChartLabel: string;
lineChartLabel: string; lineChartLabel: string;
gradient = false; gradient = false;
@ -62,21 +60,14 @@ export class ServerStatsComponent implements OnInit, OnChanges {
} }
ngOnInit() { ngOnInit() {
this.setLineChartLabel(this.labels.singleAvg); this.setBarChartLabel(this.labels.singleAvg);
} }
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {
if (changes.war || changes.performanceData) { if (changes.war || changes.performanceData) {
this.initialized = { this.initializeChartData();
budget: false, Object.assign(this, [this.barChartData]);
kill: false,
revive: false,
transport: false,
flag: false
};
Object.assign(this, [this.lineChartData]);
this.activeChartSelect = this.labels.singleAvg; this.activeChartSelect = this.labels.singleAvg;
this.startDateObj = new Date(this.war.date); this.startDateObj = new Date(this.war.date);
this.startDateObj.setHours(0); this.startDateObj.setHours(0);
this.startDateObj.setMinutes(1); this.startDateObj.setMinutes(1);
@ -85,26 +76,49 @@ export class ServerStatsComponent implements OnInit, OnChanges {
selectChart(newSelection) { selectChart(newSelection) {
this.activeChartSelect = 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); 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) { initializeChartData() {
const endDate = new Date(this.war.endDate); this.tmpSingleAvg = [];
if (tmpCollection === this.tmpBudgetData) { this.tmpSingleMin = [];
this.tmpBudgetData[0].series.push(ChartUtils.getSeriesEntry(endDate, this.war.endBudgetBlufor)); this.performanceData.forEach((entry) => {
this.tmpBudgetData[1].series.push(ChartUtils.getSeriesEntry(endDate, this.war.endBudgetOpfor)); this.tmpSingleAvg.push({
} else { name: entry.entityName,
for (let j = 0; j < tmpCollection.length; j++) { value: entry.singleAvgFps
// 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]; this.tmpSingleMin.push({
if (maybeLast && maybeLast.name < endDate) { name: entry.entityName,
tmpCollection[j].series.push( value: entry.singleMinFps
ChartUtils.getSeriesEntry(endDate, tmpCollection[j].series[tmpCollection[j].series.length - 1].value) });
); });
} 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) { setLineChartLabel(i18n: string) {
@ -112,4 +126,10 @@ export class ServerStatsComponent implements OnInit, OnChanges {
this.lineChartLabel = translated; 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}} {{'stats.scoreboard.tab.player' | translate}}
</a> </a>
</li> </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"> <a class="nav-link">
<mat-icon svgIcon="stats-performance" class="mat-icon-stats-performance"></mat-icon> <mat-icon svgIcon="stats-performance" class="mat-icon-stats-performance"></mat-icon>
{{'stats.scoreboard.tab.performance' | translate}} {{'stats.scoreboard.tab.performance' | translate}}
@ -109,7 +109,7 @@
<cc-server-statistics <cc-server-statistics
*ngIf="tab === 3" *ngIf="tab === 3"
[war]="war" [war]="war"
[performanceData]="[]"> [performanceData]="performanceData">
</cc-server-statistics> </cc-server-statistics>
</div> </div>

View File

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