opt-cc/static/src/app/statistic/war/fraction-stats/fraction-stats.component.ts

532 lines
20 KiB
TypeScript

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';
import {FractionHelpers} from '../../../utils/global.helpers';
@Component({
selector: 'war-detail-fraction',
templateUrl: './fraction-stats.component.html',
styleUrls: ['./fraction-stats.component.scss']
})
export class FractionStatsComponent implements OnInit, OnChanges {
@ViewChild('overview') private overviewContainer: ElementRef;
@Input() war: War;
@Input() logData: any;
@Input() isSmallLayout: boolean;
startDateObj: Date;
initialized: any;
public activeChartSelect: string;
lineChartData: any[] = [];
barChartData: any[] = [];
tmpPointData;
tmpBudgetData;
tmpKillData;
tmpFrienlyFireData;
tmpVehicleData;
tmpTransportData;
tmpReviveData;
tmpStabilizeData;
tmpPlayerCountData;
colorScheme;
fractionNameBlufor;
fractionNameOpfor;
labels;
labelsKeys;
chartYAxisLabel: string;
// line chart
showLineChart = true;
gradient = false;
yAxis = true;
xAxis = true;
legend = false;
legendTitle = false;
showXAxisLabel = false;
showYAxisLabel = true;
autoscale = true;
timeline = false;
roundDomains = true;
// bar chart
barPadding = 0;
barAnimations = false;
constructor(private translate: TranslateService) {
}
ngOnInit() {
this.setChartYAxisLabel(this.labels.points);
}
ngOnChanges(changes: SimpleChanges) {
if (changes.war || changes.logData) {
this.fractionNameBlufor = FractionHelpers.getFractionName(this.war, 'BLUFOR');
this.fractionNameOpfor = FractionHelpers.getFractionName(this.war, 'OPFOR');
this.colorScheme = {
domain: [
FractionHelpers.getFractionColor('BLUFOR', this.war),
FractionHelpers.getFractionColor('OPFOR', this.war),
FractionHelpers.getFractionColor('BLUFOR', this.war, 'LIGHT'),
FractionHelpers.getFractionColor('OPFOR', this.war, 'LIGHT'),
FractionHelpers.getFractionColor('BLUFOR', this.war, 'DARK'),
FractionHelpers.getFractionColor('OPFOR', this.war, 'DARK'),
FractionHelpers.getFractionColor('BLUFOR', this.war, 'GREY'),
FractionHelpers.getFractionColor('OPFOR', this.war, 'GREY'),
]
};
this.initialized = {
budget: false,
kill: false,
revive: false,
transport: false,
flag: false,
playerCount: false
};
this.initializeToggleButtons();
Object.assign(this, [this.lineChartData, this.barChartData]);
this.activeChartSelect = this.labels.points;
this.startDateObj = new Date(this.war.date);
this.startDateObj.setHours(0);
this.startDateObj.setMinutes(1);
this.loadFractionData();
}
}
/**
* show only labels for for data that is available,
* to not end up with empty charts in old battles
*/
initializeToggleButtons() {
const newLabels = {};
if (this.logData.points && this.logData.points.length > 0) {
newLabels['points'] = 'stats.fraction.select.points';
}
if (this.logData.budget && this.logData.budget.length > 0) {
newLabels['budget'] = 'stats.fraction.select.budget';
}
if (this.logData.kill && this.logData.kill.length > 0) {
newLabels['kill'] = 'stats.fraction.select.kills';
newLabels['friendlyFire'] = 'stats.fraction.select.friendly.fire';
}
if (this.logData.vehicle && this.logData.vehicle.length > 0) {
newLabels['vehicle'] = 'stats.fraction.select.vehicle.kills';
}
if (this.logData.transport && this.logData.transport.length > 0) {
newLabels['transport'] = 'stats.fraction.select.air.transport';
}
if (this.logData.revive && this.logData.revive.length > 0) {
newLabels['revive'] = 'stats.fraction.select.revive';
newLabels['stabilize'] = 'stats.fraction.select.stabilize';
}
if (this.logData.flag && this.logData.flag.length > 0) {
newLabels['flag'] = 'stats.fraction.select.flag';
}
if (this.logData.playerCount && this.logData.playerCount.length > 0) {
newLabels['playerCount'] = 'stats.fraction.select.player.count';
}
this.labels = newLabels;
this.labelsKeys = Object.keys(this.labels);
}
selectChart(newSelection) {
this.activeChartSelect = newSelection;
this.setChartYAxisLabel(this.activeChartSelect);
if (this.activeChartSelect !== this.labels.flag) {
this.showLineChart = true;
switch (this.activeChartSelect) {
case this.labels.points:
this.lineChartData = this.tmpPointData;
break;
case this.labels.budget:
this.initBudgetData();
this.lineChartData = this.tmpBudgetData;
break;
case this.labels.kill:
this.initKillData();
this.lineChartData = this.tmpKillData;
break;
case this.labels.friendlyFire:
this.initKillData();
this.lineChartData = this.tmpFrienlyFireData;
break;
case this.labels.vehicle:
this.initVehicleData();
this.lineChartData = this.tmpVehicleData;
break;
case this.labels.revive:
this.initRevive();
this.lineChartData = this.tmpReviveData;
break;
case this.labels.stabilize:
this.initRevive();
this.lineChartData = this.tmpStabilizeData;
break;
case this.labels.transport:
this.initTransportData();
this.lineChartData = this.tmpTransportData;
break;
case this.labels.playerCount:
this.initPlayerCountData();
this.lineChartData = this.tmpPlayerCountData;
break;
}
} else {
this.initFlagHoldData();
this.showLineChart = false;
}
}
loadFractionData() {
this.initializeTempCollections();
this.initPointData();
this.showLineChart = true;
this.lineChartData = this.tmpPointData;
}
initPointData() {
this.logData.points.forEach(pointEntry => {
this.tmpPointData[0].series.push(
ChartUtils.getSeriesEntry(new Date(pointEntry.time), pointEntry.ptBlufor));
this.tmpPointData[1].series.push(
ChartUtils.getSeriesEntry(new Date(pointEntry.time), pointEntry.ptOpfor));
});
this.addFinalTimeData(this.tmpPointData);
}
initBudgetData() {
if (this.initialized.budget) {
return;
}
this.logData.budget.forEach(budgetEntry => {
const budgetEntryDate = new Date(budgetEntry.time);
const fractionChange = budgetEntry.fraction === 'BLUFOR' ? 0 : 1;
const fractionOld = budgetEntry.fraction !== 'BLUFOR' ? 0 : 1;
if (ChartUtils.isOneMinuteAhead(budgetEntryDate, this.tmpBudgetData)) {
this.tmpBudgetData[fractionChange].series.push(ChartUtils.getSeriesEntry(new Date(budgetEntry.time), budgetEntry.newBudget));
this.tmpBudgetData[fractionOld].series.push(ChartUtils.getSeriesEntry(new Date(budgetEntry.time),
this.tmpBudgetData[fractionOld].series[this.tmpBudgetData[fractionOld].series.length - 1].value));
}
});
this.addFinalTimeData(this.tmpBudgetData);
this.initialized.budget = true;
}
initKillData() {
if (this.initialized.kill) {
return;
}
let killCountBlufor = 0, killCountOpfor = 0, ffKillCountBlufor = 0, ffKillCountOpfor = 0;
for (const {killEntry, index} of this.logData.kill.map((kill, pos) => ({killEntry: kill, index: pos}))) {
const killEntryDate = new Date(killEntry.time);
if (killEntry.friendlyFire === false) {
if (killEntry.fraction === 'BLUFOR') {
killCountBlufor++;
}
if (killEntry.fraction === 'OPFOR') {
killCountOpfor++;
}
if (ChartUtils.isOneMinuteAhead(killEntryDate, this.tmpKillData)) {
this.tmpKillData[0].series.push(ChartUtils.getSeriesEntry(killEntryDate, killCountBlufor));
this.tmpKillData[1].series.push(ChartUtils.getSeriesEntry(killEntryDate, killCountOpfor));
}
} else {
if (killEntry.fraction === 'BLUFOR') {
ffKillCountBlufor++;
}
if (killEntry.fraction === 'OPFOR') {
ffKillCountOpfor++;
}
if (ChartUtils.isOneMinuteAhead(killEntryDate, this.tmpFrienlyFireData)) {
this.tmpFrienlyFireData[0].series.push(ChartUtils.getSeriesEntry(killEntryDate, ffKillCountBlufor));
this.tmpFrienlyFireData[1].series.push(ChartUtils.getSeriesEntry(killEntryDate, ffKillCountOpfor));
}
}
if (index === this.logData.kill.length - 1) {
this.tmpKillData[0].series.push(ChartUtils.getSeriesEntry(killEntryDate, killCountBlufor));
this.tmpKillData[1].series.push(ChartUtils.getSeriesEntry(killEntryDate, killCountOpfor));
this.tmpFrienlyFireData[0].series.push(ChartUtils.getSeriesEntry(killEntryDate, ffKillCountBlufor));
this.tmpFrienlyFireData[1].series.push(ChartUtils.getSeriesEntry(killEntryDate, ffKillCountOpfor));
}
}
this.addFinalTimeData(this.tmpKillData);
this.addFinalTimeData(this.tmpFrienlyFireData);
this.initialized.kill = true;
}
initRevive() {
if (this.initialized.revive) {
return;
}
let reviveCountBlufor = 0, reviveCountOpfor = 0, stabilizeCountBlufor = 0, stabilizeCountOpfor = 0;
for (const {reviveEntry, index} of this.logData.revive.map((revive, pos) => ({reviveEntry: revive, index: pos}))) {
const reviveEntryDate = new Date(reviveEntry.time);
if (reviveEntry.stabilized === false) {
if (reviveEntry.fraction === 'BLUFOR') {
reviveCountBlufor++;
} else {
reviveCountOpfor++;
}
if (ChartUtils.isOneMinuteAhead(reviveEntryDate, this.tmpReviveData)) {
this.tmpReviveData[0].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, reviveCountBlufor));
this.tmpReviveData[1].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, reviveCountOpfor));
}
} else {
if (reviveEntry.fraction === 'BLUFOR') {
stabilizeCountBlufor++;
} else {
stabilizeCountOpfor++;
}
if (ChartUtils.isOneMinuteAhead(reviveEntryDate, this.tmpStabilizeData)) {
this.tmpStabilizeData[0].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, stabilizeCountBlufor));
this.tmpStabilizeData[1].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, stabilizeCountOpfor));
}
}
if (index === this.logData.revive.length - 1) {
this.tmpReviveData[0].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, reviveCountBlufor));
this.tmpReviveData[1].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, reviveCountOpfor));
this.tmpStabilizeData[0].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, stabilizeCountBlufor));
this.tmpStabilizeData[1].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, stabilizeCountOpfor));
}
}
this.addFinalTimeData(this.tmpReviveData);
this.addFinalTimeData(this.tmpStabilizeData);
this.initialized.revive = true;
}
initVehicleData() {
if (this.initialized.vehicle) {
return;
}
let vehicleKillCountBlufor = 0, vehicleKillCountOpfor = 0, vehicleLightCountBlufor = 0, vehicleHeavyCountBlufor = 0,
vehicleAirCountBlufor = 0, vehicleLightCountOpfor = 0, vehicleHeavyCountOpfor = 0, vehicleAirCountOpfor = 0;
for (const {transportEntry: vehicleEntry, index} of this.logData.vehicle.map((transport, pos) => ({
transportEntry: transport,
index: pos
}))) {
const vehicleEntryDate = new Date(vehicleEntry.time);
if (vehicleEntry.fraction === 'BLUFOR') {
vehicleKillCountBlufor++;
if (vehicleEntry.vehicleClass) {
switch (vehicleEntry.vehicleClass) {
case 'LIGHT':
vehicleLightCountBlufor++;
break;
case 'HEAVY':
vehicleHeavyCountBlufor++;
break;
case 'AIR':
vehicleAirCountBlufor++;
break;
}
}
} else {
vehicleKillCountOpfor++;
if (vehicleEntry.vehicleClass) {
switch (vehicleEntry.vehicleClass) {
case 'LIGHT':
vehicleLightCountOpfor++;
break;
case 'HEAVY':
vehicleHeavyCountOpfor++;
break;
case 'AIR':
vehicleAirCountOpfor++;
break;
}
}
}
if (ChartUtils.isOneMinuteAhead(vehicleEntryDate, this.tmpVehicleData) || index === this.logData.vehicle.length - 1) {
this.tmpVehicleData[0].series.push(ChartUtils.getSeriesEntry(vehicleEntryDate, vehicleKillCountBlufor));
this.tmpVehicleData[1].series.push(ChartUtils.getSeriesEntry(vehicleEntryDate, vehicleKillCountOpfor));
if (vehicleEntry.vehicleClass) {
this.tmpVehicleData[2].series.push(ChartUtils.getSeriesEntry(vehicleEntryDate, vehicleLightCountBlufor));
this.tmpVehicleData[3].series.push(ChartUtils.getSeriesEntry(vehicleEntryDate, vehicleLightCountOpfor));
this.tmpVehicleData[4].series.push(ChartUtils.getSeriesEntry(vehicleEntryDate, vehicleHeavyCountBlufor));
this.tmpVehicleData[5].series.push(ChartUtils.getSeriesEntry(vehicleEntryDate, vehicleHeavyCountOpfor));
this.tmpVehicleData[6].series.push(ChartUtils.getSeriesEntry(vehicleEntryDate, vehicleAirCountBlufor));
this.tmpVehicleData[7].series.push(ChartUtils.getSeriesEntry(vehicleEntryDate, vehicleAirCountOpfor));
}
}
}
this.addFinalTimeData(this.tmpVehicleData);
this.initialized.vehicle = true;
}
initTransportData() {
if (this.initialized.transport) {
return;
}
let transportCountBlufor = 0, transportCountOpfor = 0;
for (const {transportEntry, index} of this.logData.transport.map((transport, pos) => ({
transportEntry: transport,
index: pos
}))) {
const transportEntryDate = new Date(transportEntry.time);
if (transportEntry.fraction === 'BLUFOR') {
transportCountBlufor++;
} else {
transportCountOpfor++;
}
if (ChartUtils.isOneMinuteAhead(transportEntryDate, this.tmpTransportData) ||
index === this.logData.transport.length - 1) {
this.tmpTransportData[0].series.push(ChartUtils.getSeriesEntry(transportEntryDate, transportCountBlufor));
this.tmpTransportData[1].series.push(ChartUtils.getSeriesEntry(transportEntryDate, transportCountOpfor));
}
}
this.addFinalTimeData(this.tmpTransportData);
this.initialized.transport = true;
}
initPlayerCountData() {
if (this.initialized.playerCount) {
return;
}
this.logData.playerCount.forEach(playerCountEntry => {
this.tmpPlayerCountData[0].series.push(
ChartUtils.getSeriesEntry(new Date(playerCountEntry.time), playerCountEntry.countBlufor));
this.tmpPlayerCountData[1].series.push(
ChartUtils.getSeriesEntry(new Date(playerCountEntry.time), playerCountEntry.countOpfor));
});
this.initialized.playerCount = true;
this.addFinalTimeData(this.tmpPlayerCountData);
}
initFlagHoldData() {
if (this.initialized.flag) {
return;
}
let flagStatusBlufor = true;
let flagStatusOpfor = true;
const flagStatusMap = {
blufor: {0: flagStatusBlufor},
opfor: {0: flagStatusOpfor},
};
this.logData.flag.forEach((flagEntry) => {
if (flagEntry.flagFraction === 'BLUFOR') {
flagStatusBlufor = !flagEntry.capture;
} else {
flagStatusOpfor = !flagEntry.capture;
}
const entryMinute = Math.round((new Date(flagEntry.time).getTime() - new Date(this.war.date).getTime()) / 60000);
flagStatusMap.blufor[entryMinute] = flagStatusBlufor;
flagStatusMap.opfor[entryMinute] = flagStatusOpfor;
});
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: this.fractionNameBlufor,
value: flagStatusMap.blufor[lastExistingIdx] ? 1 : 0
}
]
});
data.push({
name: t,
series: [
{
name: this.fractionNameOpfor,
value: flagStatusMap.opfor[lastExistingIdx] ? -1 : 0
}
]
});
}
this.barChartData = data;
this.initialized.flag = true;
}
initializeTempCollections() {
this.tmpPointData = ChartUtils.getMultiDataArray(this.fractionNameBlufor, this.fractionNameOpfor);
this.tmpBudgetData = ChartUtils.getMultiDataArray(this.fractionNameBlufor, this.fractionNameOpfor);
this.tmpKillData = ChartUtils.getMultiDataArray(this.fractionNameBlufor, this.fractionNameOpfor);
this.tmpFrienlyFireData = ChartUtils.getMultiDataArray(this.fractionNameBlufor, this.fractionNameOpfor);
this.tmpVehicleData = ChartUtils.getMultiDataArray(this.fractionNameBlufor, this.fractionNameOpfor,
this.fractionNameBlufor.concat(' Leicht'), this.fractionNameOpfor.concat(' Leicht'), this.fractionNameBlufor.concat(' Schwer'),
this.fractionNameOpfor.concat(' Schwer'), this.fractionNameBlufor.concat(' Luft'), this.fractionNameOpfor.concat(' Luft'));
this.tmpTransportData = ChartUtils.getMultiDataArray(this.fractionNameBlufor, this.fractionNameOpfor);
this.tmpReviveData = ChartUtils.getMultiDataArray(this.fractionNameBlufor, this.fractionNameOpfor);
this.tmpStabilizeData = ChartUtils.getMultiDataArray(this.fractionNameBlufor, this.fractionNameOpfor);
this.tmpPlayerCountData = ChartUtils.getMultiDataArray(this.fractionNameBlufor, this.fractionNameOpfor);
[this.tmpKillData, this.tmpFrienlyFireData, this.tmpVehicleData, this.tmpReviveData, this.tmpStabilizeData,
this.tmpTransportData].forEach(tmp => {
[0, 1].forEach(index => {
tmp[index].series.push(ChartUtils.getSeriesEntry(this.startDateObj, 0));
});
});
this.tmpBudgetData[0].series.push(ChartUtils.getSeriesEntry(this.startDateObj, this.war.budgetBlufor));
this.tmpBudgetData[1].series.push(ChartUtils.getSeriesEntry(this.startDateObj, this.war.budgetOpfor));
}
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)
);
}
}
}
}
setChartYAxisLabel(i18n: string) {
this.translate.get(i18n).subscribe((translated) => {
this.chartYAxisLabel = translated;
});
}
axisFormatX(val) {
if (val % 10 === 0) {
return val;
} else {
return '';
}
}
axisFormatY(val) {
if (val === 1) {
return this.fractionNameBlufor;
}
if (val === -1) {
return this.fractionNameOpfor;
}
return '';
}
}