/// import {Component, ElementRef, ViewChild} from "@angular/core"; import {ActivatedRoute, Router} from "@angular/router"; import {WarService} from "../../services/logs/war.service"; import {War} from "../../models/model-interfaces"; import {LogsService} from "../../services/logs/logs.service"; import {TabsetComponent} from "ngx-bootstrap"; import * as d3 from "d3"; import {ChartUtils} from "../../utils/chart-utils"; @Component({ selector: 'war-detail', templateUrl: './war-detail.component.html', styleUrls: ['./war-detail.component.css', '../../style/list-entry.css', '../../style/hide-scrollbar.css'] }) export class WarDetailComponent { @ViewChild('overview') private overviewContainer: ElementRef; @ViewChild('staticTabs') staticTabs: TabsetComponent; war: War = {players: []}; public chartSelectModel: string; fractionRadioSelect: string; playerChart: any[] = []; cellHeight = 40; rows = []; reorderable: boolean = false; customClasses = { sortAscending: 'glyphicon glyphicon-triangle-top', sortDescending: 'glyphicon glyphicon-triangle-bottom', }; lineChartData: any[] = []; areaChartData: any[] = []; tmpPointData; tmpBudgetData; tmpKillData; tmpFrienlyFireData; tmpTransportData; tmpReviveData; tmpStabilizeData; tmpFlagCaptureData; colorScheme = { domain: ['#0000FF', '#B22222'] }; labelPoints = 'Punkte'; labelBudget = 'Budget'; labelKill = 'Kills'; labelFriendlyFire = 'FriendlyFire'; labelTransport = 'Lufttransport'; labelRevive = 'Revive'; labelStabilize = 'Stabilisiert'; labelFlag = 'Flaggenbesitz'; lineChartLabel = this.labelPoints; showLineChart = true; stepCurve = d3.curveStepAfter; gradient = false; yAxis = true; xAxis = true; legend = false; legendTitle = false; showXAxisLabel = false; showYAxisLabel = true; autoscale = true; timeline = false; roundDomains = true; fractionChartsInitialized: boolean = false; startDateObj; dataMode: string = 'Summe'; dataInterval: number = 0; logData; constructor(private route: ActivatedRoute, private router: Router, private warService: WarService, private logsService: LogsService) { } ngOnInit() { this.route.params .map(params => params['id']) .filter(id => id != undefined) .flatMap(id => this.warService.getWar(id)) .subscribe(war => { this.war = war; this.rows = war.players; this.playerChart = ChartUtils.getSingleDataArray('CSAT', war.playersOpfor, 'NATO', war.playersBlufor); this.fractionChartsInitialized = false; Object.assign(this, [this.playerChart, this.lineChartData, this.areaChartData]); this.chartSelectModel = this.labelPoints; this.startDateObj = new Date(this.war.date); this.startDateObj.setHours(0); this.startDateObj.setMinutes(1); this.fractionRadioSelect = undefined; this.staticTabs.tabs[0].active = true; this.scrollOverviewTop(); }); } filterPlayersByFraction(fraction?: string) { if (fraction) { this.rows = this.war.players.filter((player) => { return player.fraction === fraction; }) } else { this.rows = this.war.players; } } selectChart() { if (this.chartSelectModel !== this.labelFlag) { this.showLineChart = true; this.lineChartLabel = this.chartSelectModel; switch (this.chartSelectModel) { case this.labelPoints: this.lineChartData = this.tmpPointData; break; case this.labelBudget: this.lineChartData = this.tmpBudgetData; break; case this.labelKill: this.lineChartData = this.tmpKillData; break; case this.labelFriendlyFire: this.lineChartData = this.tmpFrienlyFireData; break; case this.labelRevive: this.lineChartData = this.tmpReviveData; break; case this.labelStabilize: this.lineChartData = this.tmpStabilizeData; break; case this.labelTransport: this.lineChartData = this.tmpTransportData; break; } } else { this.showLineChart = false; this.areaChartData = this.tmpFlagCaptureData; } } selectPlayerDetail(player) { if (player && player.selected && player.selected.length > 0) { this.router.navigate(['../../campaign-player/' + this.war.campaign + '/' + player.selected[0].name], {relativeTo: this.route}); } } scrollOverviewTop() { try { this.overviewContainer.nativeElement.scrollTop = 0; } catch (err) { } } toggleDataMode(interval, entryString) { this.dataInterval = interval; this.dataMode = entryString; this.initTransportData(); this.lineChartData = this.tmpTransportData; } loadFractionData() { if (this.fractionChartsInitialized) { return; } this.tmpPointData = ChartUtils.getMultiDataArray('NATO', 'CSAT'); this.tmpBudgetData = ChartUtils.getMultiDataArray('NATO', 'CSAT'); this.tmpKillData = ChartUtils.getMultiDataArray('NATO', 'CSAT'); this.tmpFrienlyFireData = ChartUtils.getMultiDataArray('NATO', 'CSAT'); this.tmpTransportData = ChartUtils.getMultiDataArray('NATO', 'CSAT'); this.tmpReviveData = ChartUtils.getMultiDataArray('NATO', 'CSAT'); this.tmpStabilizeData = ChartUtils.getMultiDataArray('NATO', 'CSAT'); this.tmpFlagCaptureData = ChartUtils.getMultiDataArray('NATO', 'CSAT'); [this.tmpKillData, this.tmpFrienlyFireData, this.tmpReviveData, this.tmpStabilizeData, this.tmpTransportData].forEach(tmp => { [0, 1].forEach(index => { tmp[index].series.push(ChartUtils.getSeriesEntry(this.startDateObj, 0)); }) }); this.logsService.getFullLog(this.war._id).subscribe((data) => { this.logData = data; this.initPointData(); this.initBudgetData(); this.initKillData(); this.initRevive(); this.initTransportData(); this.initFlagHoldData(); this.addFinalTimeDataEntriesAndPopulate(new Date(this.war.endDate)); this.fractionChartsInitialized = true; }); } 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)); }); } initBudgetData() { this.tmpBudgetData[0].series.push(ChartUtils.getSeriesEntry(this.startDateObj, this.war.budgetBlufor)); this.tmpBudgetData[1].series.push(ChartUtils.getSeriesEntry(this.startDateObj, this.war.budgetOpfor)); // This adds an entry for both fractions on every event for (let i = 0; i < this.logData.budget.length; i++) { const budgetEntry = this.logData.budget[i]; const fractionChange = budgetEntry.fraction === 'BLUFOR' ? 0 : 1; const fractionOld = budgetEntry.fraction !== 'BLUFOR' ? 0 : 1; if (WarDetailComponent.isTwoMinutesAhead(budgetEntry, this.tmpBudgetData, i, this.logData.budget.length)) { 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.tmpBudgetData[0].series.push(ChartUtils.getSeriesEntry(new Date(this.war.endDate), this.war.endBudgetBlufor)); this.tmpBudgetData[1].series.push(ChartUtils.getSeriesEntry(new Date(this.war.endDate), this.war.endBudgetOpfor)); } initKillData() { let killCountBlufor = 0, killCountOpfor = 0, ffKillCountBlufor = 0, ffKillCountOpfor = 0 for (let i = 0; i < this.logData.kill.length; i++) { const killEntry = this.logData.kill[i]; if (killEntry.friendlyFire === false) { if (killEntry.fraction === 'BLUFOR') { killCountBlufor++; } else { killCountOpfor++; } if (WarDetailComponent.isTwoMinutesAhead(killEntry, this.tmpKillData, i, this.logData.kill.length)) { this.tmpKillData[0].series.push(ChartUtils.getSeriesEntry(new Date(killEntry.time), killCountBlufor)); this.tmpKillData[1].series.push(ChartUtils.getSeriesEntry(new Date(killEntry.time), killCountOpfor)); } } else { if (killEntry.fraction === 'BLUFOR') { ffKillCountBlufor++; } else { ffKillCountOpfor++; } if (WarDetailComponent.isTwoMinutesAhead(killEntry, this.tmpFrienlyFireData, i, this.logData.kill.length)) { this.tmpFrienlyFireData[0].series.push(ChartUtils.getSeriesEntry(new Date(killEntry.time), ffKillCountBlufor)); this.tmpFrienlyFireData[1].series.push(ChartUtils.getSeriesEntry(new Date(killEntry.time), ffKillCountOpfor)); } } } } initRevive() { let reviveCountBlufor = 0, reviveCountOpfor = 0, stabilizeCountBlufor = 0, stabilizeCountOpfor = 0; for (let i = 0; i < this.logData.revive.length; i++) { const reviveEntry = this.logData.revive[i]; if (reviveEntry.stabilized === false) { if (reviveEntry.fraction === 'BLUFOR') { reviveCountBlufor++; } else { reviveCountOpfor++; } if (WarDetailComponent.isTwoMinutesAhead(reviveEntry, this.tmpReviveData, i, this.logData.revive.length)) { this.tmpReviveData[0].series.push(ChartUtils.getSeriesEntry(new Date(reviveEntry.time), reviveCountBlufor)); this.tmpReviveData[1].series.push(ChartUtils.getSeriesEntry(new Date(reviveEntry.time), reviveCountOpfor)); } } else { if (reviveEntry.fraction === 'BLUFOR') { stabilizeCountBlufor++; } else { stabilizeCountOpfor++; } if (WarDetailComponent.isTwoMinutesAhead(reviveEntry, this.tmpStabilizeData, i, this.logData.revive.length)) { this.tmpStabilizeData[0].series.push(ChartUtils.getSeriesEntry(new Date(reviveEntry.time), stabilizeCountBlufor)); this.tmpStabilizeData[1].series.push(ChartUtils.getSeriesEntry(new Date(reviveEntry.time), stabilizeCountOpfor)); } } } } initTransportData() { let transportCountBlufor = 0, transportCountOpfor = 0; for (let i = 0; i < this.logData.transport.length; i++) { const transportEntry = this.logData.transport[i]; if (transportEntry.fraction === 'BLUFOR') { transportCountBlufor++; } else { transportCountOpfor++; } if (WarDetailComponent.isTwoMinutesAhead(transportEntry, this.tmpTransportData, i, this.logData.transport.length)) { this.tmpTransportData[0].series.push(ChartUtils.getSeriesEntry(new Date(transportEntry.time), transportCountBlufor)); this.tmpTransportData[1].series.push(ChartUtils.getSeriesEntry(new Date(transportEntry.time), transportCountOpfor)); } } } initFlagHoldData() { let flagStatusBlufor = true; let flagStatusOpfor = true; this.tmpFlagCaptureData[0].series.push(ChartUtils.getSeriesEntry(this.startDateObj, flagStatusBlufor)); this.tmpFlagCaptureData[1].series.push(ChartUtils.getSeriesEntry(this.startDateObj, flagStatusOpfor)); this.logData.flag.forEach(flagEntry => { if (flagEntry.flagFraction === 'BLUFOR') { flagStatusBlufor = !flagEntry.capture } else { flagStatusOpfor = !flagEntry.capture; } this.tmpFlagCaptureData[flagEntry.flagFraction === 'BLUFOR' ? 0 : 1].series.push( ChartUtils.getSeriesEntry(new Date(flagEntry.time), flagEntry.fraction === 'BLUFOR' ? flagStatusBlufor : flagStatusOpfor) ) }); } private static isTwoMinutesAhead(entry: any, tmpData: any, index: number, logDataLength: number): boolean { return new Date(entry.time).getTime() >= tmpData[0].series[tmpData[0].series.length - 1].name.getTime() + (1.5 * 60000) || index === logDataLength - 1 } addFinalTimeDataEntriesAndPopulate(endDate) { [this.tmpPointData, this.tmpBudgetData, this.tmpTransportData, this.tmpReviveData, this.tmpStabilizeData, this.tmpKillData, this.tmpFrienlyFireData, this.tmpFlagCaptureData].forEach(tmp => { for (let j in [0, 1]) { if (tmp[j].series[tmp[j].series.length - 1].name < endDate) { tmp[j].series.push(ChartUtils.getSeriesEntry(endDate, tmp[j].series[tmp[j].series.length - 1].value)); } } }); this.showLineChart = true; this.lineChartLabel = this.labelPoints; this.lineChartData = this.tmpPointData; } }