Use stacked bar chart for flag capture visualization (CC-72)
parent
20321def38
commit
90510eac93
|
@ -28,20 +28,25 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="!showLineChart" class="chart-container">
|
<div *ngIf="!showLineChart" class="chart-container">
|
||||||
<ngx-charts-area-chart
|
<ngx-charts-bar-vertical-stacked
|
||||||
[scheme]="colorScheme"
|
[scheme]="colorScheme"
|
||||||
[results]="areaChartData"
|
[results]="barChartData"
|
||||||
[xAxis]="xAxis"
|
[xAxis]="xAxis"
|
||||||
[yAxis]="yAxis"
|
[yAxis]="barShowYAxis"
|
||||||
[curve]="stepCurve"
|
|
||||||
[legend]="legend"
|
[legend]="legend"
|
||||||
[legendTitle]="legendTitle"
|
[legendTitle]="legendTitle"
|
||||||
[showXAxisLabel]="showXAxisLabel"
|
[showXAxisLabel]="barShowXAxisLabel"
|
||||||
[showYAxisLabel]="showYAxisLabel"
|
[showYAxisLabel]="showYAxisLabel"
|
||||||
[yAxisLabel]="labelFlag"
|
[animations]="barAnimations"
|
||||||
[autoScale]="autoscale"
|
[barPadding]="barPadding"
|
||||||
[timeline]="timeline"
|
[xAxisTickFormatting]="axisFormat"
|
||||||
[roundDomains]="false">
|
[xAxisLabel]="'Minute'">
|
||||||
</ngx-charts-area-chart>
|
<ng-template #tooltipTemplate let-model="model">
|
||||||
|
<small>{{'stats.fraction.tooltip.flag.minute' | translate}} {{model.series}}</small>
|
||||||
|
<div>{{model.name}} {{'stats.fraction.tooltip.flag.flag' | translate}}</div>
|
||||||
|
<div *ngIf="model.value === 0">{{'stats.fraction.tooltip.flag.lost' | translate}}</div>
|
||||||
|
<div *ngIf="model.value !== 0">{{'stats.fraction.tooltip.flag.safe' | translate}}</div>
|
||||||
|
</ng-template>
|
||||||
|
</ngx-charts-bar-vertical-stacked>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {TranslateService} from '@ngx-translate/core';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'war-detail-fraction',
|
selector: 'war-detail-fraction',
|
||||||
templateUrl: './fraction-stats.component.html',
|
templateUrl: './fraction-stats.component.html',
|
||||||
styleUrls: ['./fraction-stats.component.css', '../../../style/list-entry.css', '../../../style/hide-scrollbar.css']
|
styleUrls: ['./fraction-stats.component.scss', '../../../style/list-entry.css', '../../../style/hide-scrollbar.css']
|
||||||
})
|
})
|
||||||
export class FractionStatsComponent implements OnInit, OnChanges {
|
export class FractionStatsComponent implements OnInit, OnChanges {
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ export class FractionStatsComponent implements OnInit, OnChanges {
|
||||||
public activeChartSelect: string;
|
public activeChartSelect: string;
|
||||||
|
|
||||||
lineChartData: any[] = [];
|
lineChartData: any[] = [];
|
||||||
areaChartData: any[] = [];
|
barChartData: any[] = [];
|
||||||
|
|
||||||
tmpPointData;
|
tmpPointData;
|
||||||
tmpBudgetData;
|
tmpBudgetData;
|
||||||
|
@ -38,7 +38,6 @@ export class FractionStatsComponent implements OnInit, OnChanges {
|
||||||
tmpTransportData;
|
tmpTransportData;
|
||||||
tmpReviveData;
|
tmpReviveData;
|
||||||
tmpStabilizeData;
|
tmpStabilizeData;
|
||||||
tmpFlagCaptureData;
|
|
||||||
tmpPlayerCountData;
|
tmpPlayerCountData;
|
||||||
|
|
||||||
colorScheme = {
|
colorScheme = {
|
||||||
|
@ -64,6 +63,11 @@ export class FractionStatsComponent implements OnInit, OnChanges {
|
||||||
timeline = false;
|
timeline = false;
|
||||||
roundDomains = true;
|
roundDomains = true;
|
||||||
|
|
||||||
|
barPadding = 0;
|
||||||
|
barAnimations = false;
|
||||||
|
barShowYAxis = false;
|
||||||
|
barShowXAxisLabel = true;
|
||||||
|
|
||||||
constructor(private translate: TranslateService) {
|
constructor(private translate: TranslateService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +88,7 @@ export class FractionStatsComponent implements OnInit, OnChanges {
|
||||||
|
|
||||||
this.initializeToggleButtons();
|
this.initializeToggleButtons();
|
||||||
|
|
||||||
Object.assign(this, [this.lineChartData, this.areaChartData]);
|
Object.assign(this, [this.lineChartData, this.barChartData]);
|
||||||
this.activeChartSelect = this.labels.points;
|
this.activeChartSelect = this.labels.points;
|
||||||
|
|
||||||
this.startDateObj = new Date(this.war.date);
|
this.startDateObj = new Date(this.war.date);
|
||||||
|
@ -175,7 +179,6 @@ export class FractionStatsComponent implements OnInit, OnChanges {
|
||||||
} else {
|
} else {
|
||||||
this.initFlagHoldData();
|
this.initFlagHoldData();
|
||||||
this.showLineChart = false;
|
this.showLineChart = false;
|
||||||
this.areaChartData = this.tmpFlagCaptureData;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,21 +405,49 @@ export class FractionStatsComponent implements OnInit, OnChanges {
|
||||||
}
|
}
|
||||||
let flagStatusBlufor = true;
|
let flagStatusBlufor = true;
|
||||||
let flagStatusOpfor = true;
|
let flagStatusOpfor = true;
|
||||||
this.tmpFlagCaptureData[0].series.push(ChartUtils.getSeriesEntry(this.startDateObj, flagStatusBlufor));
|
const flagStatusMap = {
|
||||||
this.tmpFlagCaptureData[1].series.push(ChartUtils.getSeriesEntry(this.startDateObj, flagStatusOpfor));
|
blufor: {0: flagStatusBlufor},
|
||||||
|
opfor: {0: flagStatusOpfor},
|
||||||
|
};
|
||||||
|
|
||||||
this.logData.flag.forEach(flagEntry => {
|
this.logData.flag.forEach((flagEntry) => {
|
||||||
if (flagEntry.flagFraction === 'BLUFOR') {
|
if (flagEntry.flagFraction === 'BLUFOR') {
|
||||||
flagStatusBlufor = !flagEntry.capture;
|
flagStatusBlufor = !flagEntry.capture;
|
||||||
} else {
|
} else {
|
||||||
flagStatusOpfor = !flagEntry.capture;
|
flagStatusOpfor = !flagEntry.capture;
|
||||||
}
|
}
|
||||||
this.tmpFlagCaptureData[flagEntry.flagFraction === 'BLUFOR' ? 0 : 1].series.push(
|
const entryMinute = Math.round((new Date(flagEntry.time).getTime() - new Date(this.war.date).getTime()) / 60000);
|
||||||
ChartUtils.getSeriesEntry(new Date(flagEntry.time), flagEntry.flagFraction === 'BLUFOR' ? flagStatusBlufor : flagStatusOpfor)
|
flagStatusMap.blufor[entryMinute] = flagStatusBlufor;
|
||||||
);
|
flagStatusMap.opfor[entryMinute] = flagStatusOpfor;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.addFinalTimeData(this.tmpFlagCaptureData);
|
const data = [];
|
||||||
|
let lastExistingIdx = 0;
|
||||||
|
const finishMinute = Math.round((new Date(this.war.endDate).getTime() - new Date(this.war.date).getTime()) / 60000);
|
||||||
|
for (let t = 0; t <= finishMinute; t++) {
|
||||||
|
if (flagStatusMap.blufor.hasOwnProperty(t) && flagStatusMap.opfor.hasOwnProperty(t)) {
|
||||||
|
lastExistingIdx = t;
|
||||||
|
}
|
||||||
|
data.push({
|
||||||
|
name: t,
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: Fraction.BLUFOR,
|
||||||
|
value: flagStatusMap.blufor[lastExistingIdx] ? 1 : 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
data.push({
|
||||||
|
name: t,
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: Fraction.OPFOR,
|
||||||
|
value: flagStatusMap.opfor[lastExistingIdx] ? -1 : 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.barChartData = data;
|
||||||
this.initialized.flag = true;
|
this.initialized.flag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,7 +466,6 @@ export class FractionStatsComponent implements OnInit, OnChanges {
|
||||||
this.tmpTransportData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR);
|
this.tmpTransportData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR);
|
||||||
this.tmpReviveData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR);
|
this.tmpReviveData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR);
|
||||||
this.tmpStabilizeData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR);
|
this.tmpStabilizeData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR);
|
||||||
this.tmpFlagCaptureData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR);
|
|
||||||
this.tmpPlayerCountData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR);
|
this.tmpPlayerCountData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR);
|
||||||
|
|
||||||
[this.tmpKillData, this.tmpFrienlyFireData, this.tmpVehicleData, this.tmpReviveData, this.tmpStabilizeData,
|
[this.tmpKillData, this.tmpFrienlyFireData, this.tmpVehicleData, this.tmpReviveData, this.tmpStabilizeData,
|
||||||
|
@ -471,4 +501,12 @@ export class FractionStatsComponent implements OnInit, OnChanges {
|
||||||
this.lineChartLabel = translated;
|
this.lineChartLabel = translated;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
axisFormat(val) {
|
||||||
|
if (val % 10 === 0) {
|
||||||
|
return val
|
||||||
|
} else {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
[showXAxisLabel]="showXAxisLabel"
|
[showXAxisLabel]="showXAxisLabel"
|
||||||
[showYAxisLabel]="showYAxisLabel"
|
[showYAxisLabel]="showYAxisLabel"
|
||||||
[yAxisLabel]="barChartLabel"
|
[yAxisLabel]="barChartLabel"
|
||||||
[barPadding]="2"
|
[barPadding]="barPadding"
|
||||||
[roundDomains]="roundDomains">
|
[roundDomains]="roundDomains">
|
||||||
</ngx-charts-bar-vertical>
|
</ngx-charts-bar-vertical>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -54,6 +54,7 @@ export class ServerStatsComponent implements OnInit, OnChanges {
|
||||||
autoscale = true;
|
autoscale = true;
|
||||||
timeline = false;
|
timeline = false;
|
||||||
roundDomains = true;
|
roundDomains = true;
|
||||||
|
barPadding = 2;
|
||||||
colorScheme = {
|
colorScheme = {
|
||||||
name: 'nightLights',
|
name: 'nightLights',
|
||||||
selectable: false,
|
selectable: false,
|
||||||
|
|
|
@ -28,6 +28,10 @@
|
||||||
"stats.fraction.select.stabilize": "Stabilisiert",
|
"stats.fraction.select.stabilize": "Stabilisiert",
|
||||||
"stats.fraction.select.flag": "Flaggenbesitz",
|
"stats.fraction.select.flag": "Flaggenbesitz",
|
||||||
"stats.fraction.select.player.count": "Spieleranzahl",
|
"stats.fraction.select.player.count": "Spieleranzahl",
|
||||||
|
"stats.fraction.tooltip.flag.minute": "Minute",
|
||||||
|
"stats.fraction.tooltip.flag.flag": "Flagge",
|
||||||
|
"stats.fraction.tooltip.flag.safe": "Gesichert",
|
||||||
|
"stats.fraction.tooltip.flag.lost": "Verloren",
|
||||||
|
|
||||||
"stats.performance.select.single.avg": "Spieler FPS Durchschnitt",
|
"stats.performance.select.single.avg": "Spieler FPS Durchschnitt",
|
||||||
"stats.performance.select.single.min": "Spieler FPS Minimum",
|
"stats.performance.select.single.min": "Spieler FPS Minimum",
|
||||||
|
|
|
@ -36,6 +36,10 @@
|
||||||
"stats.fraction.select.stabilize": "Stabilized",
|
"stats.fraction.select.stabilize": "Stabilized",
|
||||||
"stats.fraction.select.flag": "Flag Possession",
|
"stats.fraction.select.flag": "Flag Possession",
|
||||||
"stats.fraction.select.player.count": "Player Count",
|
"stats.fraction.select.player.count": "Player Count",
|
||||||
|
"stats.fraction.tooltip.flag.minute": "Minute",
|
||||||
|
"stats.fraction.tooltip.flag.flag": "Flag",
|
||||||
|
"stats.fraction.tooltip.flag.safe": "Safe",
|
||||||
|
"stats.fraction.tooltip.flag.lost": "Lost",
|
||||||
|
|
||||||
"stats.performance.select.single.avg": "Player FPS Average",
|
"stats.performance.select.single.avg": "Player FPS Average",
|
||||||
"stats.performance.select.single.min": "Player FPS Minimum",
|
"stats.performance.select.single.min": "Player FPS Minimum",
|
||||||
|
|
Loading…
Reference in New Issue