Compare commits
No commits in common. "325ead18c724998620df7176fa6b86bc4fc249ae" and "0621d1d2bf502e67261df41e144e3c3ae5dc5ee7" have entirely different histories.
325ead18c7
...
0621d1d2bf
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "opt-cc",
|
"name": "opt-cc",
|
||||||
"version": "1.5.0",
|
"version": "1.4.4",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -4,55 +4,9 @@
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
border-left: thin solid lightgrey;
|
border-left: thin solid lightgrey;
|
||||||
bottom: 20px;
|
bottom: 20px;
|
||||||
width: 80%;
|
width: 100%;
|
||||||
padding-left: 20px;
|
padding-left: 50px;
|
||||||
padding-right: 5%;
|
|
||||||
padding-top: 70px;
|
padding-top: 70px;
|
||||||
|
margin-left: 10px;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-back {
|
|
||||||
clear: both;
|
|
||||||
float: left;
|
|
||||||
width: 120px;
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sum-container {
|
|
||||||
width: 100%;
|
|
||||||
margin: auto;
|
|
||||||
clear: left;
|
|
||||||
padding: 2%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gauge-container {
|
|
||||||
padding: 35px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sum-bar-container {
|
|
||||||
width: 70%;
|
|
||||||
height: 400px;
|
|
||||||
margin: auto;
|
|
||||||
padding-left: 4%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.charts-parent {
|
|
||||||
clear: left;
|
|
||||||
padding-top: 50px;
|
|
||||||
width: 100%;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chart-container {
|
|
||||||
width: 42%;
|
|
||||||
min-width: 500px;
|
|
||||||
height: 300px;
|
|
||||||
padding: 15px;
|
|
||||||
margin: 2%;
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,173 +1,5 @@
|
||||||
<div class="overview" xmlns="http://www.w3.org/1999/html">
|
<div class="overview" xmlns="http://www.w3.org/1999/html">
|
||||||
|
|
||||||
<h2 class="pull-left">Spielerstatistik - {{campaignPlayer.name}}</h2>
|
<h2>{{campaignPlayer.name}}</h2>
|
||||||
<h2 class="pull-right">{{campaignPlayer.campaign.title}} Kampagne</h2>
|
|
||||||
|
|
||||||
<span class="btn btn-default btn-back" (click)="navigateBack()">< Zurück</span>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="sum-container">
|
|
||||||
<div class="gauge-container pull-left">
|
|
||||||
<ngx-charts-linear-gauge
|
|
||||||
[view]="[200, 100]"
|
|
||||||
[scheme]="colorScheme"
|
|
||||||
[value]="kdRatio"
|
|
||||||
[previousValue]="1"
|
|
||||||
[max]="maxKd"
|
|
||||||
[min]="0"
|
|
||||||
[units]="'Kill/Death'">
|
|
||||||
</ngx-charts-linear-gauge>
|
|
||||||
<span style="height: 150px; display: block;"></span>
|
|
||||||
<ngx-charts-linear-gauge
|
|
||||||
[view]="[200, 100]"
|
|
||||||
[scheme]="colorScheme"
|
|
||||||
[value]="respawnDeathRatio"
|
|
||||||
[previousValue]="0.5"
|
|
||||||
[max]="1"
|
|
||||||
[min]="0"
|
|
||||||
[units]="'Respawn/Death'">
|
|
||||||
</ngx-charts-linear-gauge>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="sum-bar-container pull-left">
|
|
||||||
<ngx-charts-bar-horizontal
|
|
||||||
[scheme]="colorSchemeBar"
|
|
||||||
[results]="sumData"
|
|
||||||
[gradient]="gradient"
|
|
||||||
[xAxis]="xAxis"
|
|
||||||
[yAxis]="yAxis"
|
|
||||||
[showXAxisLabel]="showXAxisLabel"
|
|
||||||
[showYAxisLabel]="showYAxisLabel">
|
|
||||||
</ngx-charts-bar-horizontal>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="charts-parent">
|
|
||||||
<div class="chart-container">
|
|
||||||
<ngx-charts-line-chart
|
|
||||||
[results]="killData"
|
|
||||||
[showRefLines]="showRefLines"
|
|
||||||
[showRefLabels]="showRefLabels"
|
|
||||||
[referenceLines]="killRefLines"
|
|
||||||
[scheme]="colorScheme"
|
|
||||||
[gradient]="gradient"
|
|
||||||
[xAxis]="xAxis"
|
|
||||||
[yAxis]="yAxis"
|
|
||||||
[legend]="legend"
|
|
||||||
[legendTitle]="legendTitle"
|
|
||||||
[showXAxisLabel]="showXAxisLabel"
|
|
||||||
[showYAxisLabel]="showYAxisLabel"
|
|
||||||
[yAxisLabel]="yAxisKill"
|
|
||||||
[autoScale]="autoscale"
|
|
||||||
[timeline]="timeline"
|
|
||||||
[roundDomains]="roundDomains">
|
|
||||||
</ngx-charts-line-chart>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="chart-container">
|
|
||||||
<ngx-charts-line-chart
|
|
||||||
[results]="friendlyFireData"
|
|
||||||
[showRefLines]="showRefLines"
|
|
||||||
[showRefLabels]="showRefLabels"
|
|
||||||
[referenceLines]="friendlyFireRefLines"
|
|
||||||
[scheme]="colorScheme"
|
|
||||||
[gradient]="gradient"
|
|
||||||
[xAxis]="xAxis"
|
|
||||||
[yAxis]="yAxis"
|
|
||||||
[legend]="legend"
|
|
||||||
[legendTitle]="legendTitle"
|
|
||||||
[showXAxisLabel]="showXAxisLabel"
|
|
||||||
[showYAxisLabel]="showYAxisLabel"
|
|
||||||
[yAxisLabel]="yAxisFriendlyFire"
|
|
||||||
[autoScale]="autoscale"
|
|
||||||
[timeline]="timeline"
|
|
||||||
[roundDomains]="roundDomains">
|
|
||||||
</ngx-charts-line-chart>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="chart-container">
|
|
||||||
<ngx-charts-line-chart
|
|
||||||
[results]="deathData"
|
|
||||||
[showRefLines]="showRefLines"
|
|
||||||
[showRefLabels]="showRefLabels"
|
|
||||||
[referenceLines]="deathRefLines"
|
|
||||||
[scheme]="colorScheme"
|
|
||||||
[gradient]="gradient"
|
|
||||||
[xAxis]="xAxis"
|
|
||||||
[yAxis]="yAxis"
|
|
||||||
[legend]="legend"
|
|
||||||
[legendTitle]="legendTitle"
|
|
||||||
[showXAxisLabel]="showXAxisLabel"
|
|
||||||
[showYAxisLabel]="showYAxisLabel"
|
|
||||||
[yAxisLabel]="yAxisDeath"
|
|
||||||
[autoScale]="autoscale"
|
|
||||||
[timeline]="timeline"
|
|
||||||
[roundDomains]="roundDomains">
|
|
||||||
</ngx-charts-line-chart>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="chart-container">
|
|
||||||
<ngx-charts-line-chart
|
|
||||||
[results]="respawnData"
|
|
||||||
[showRefLines]="showRefLines"
|
|
||||||
[showRefLabels]="showRefLabels"
|
|
||||||
[referenceLines]="respawnRefLines"
|
|
||||||
[scheme]="colorScheme"
|
|
||||||
[gradient]="gradient"
|
|
||||||
[xAxis]="xAxis"
|
|
||||||
[yAxis]="yAxis"
|
|
||||||
[legend]="legend"
|
|
||||||
[legendTitle]="legendTitle"
|
|
||||||
[showXAxisLabel]="showXAxisLabel"
|
|
||||||
[showYAxisLabel]="showYAxisLabel"
|
|
||||||
[yAxisLabel]="yAxisRespawn"
|
|
||||||
[autoScale]="autoscale"
|
|
||||||
[timeline]="timeline"
|
|
||||||
[roundDomains]="roundDomains">
|
|
||||||
</ngx-charts-line-chart>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="chart-container">
|
|
||||||
<ngx-charts-line-chart
|
|
||||||
[results]="reviveData"
|
|
||||||
[showRefLines]="showRefLines"
|
|
||||||
[showRefLabels]="showRefLabels"
|
|
||||||
[referenceLines]="reviveRefLines"
|
|
||||||
[scheme]="colorScheme"
|
|
||||||
[gradient]="gradient"
|
|
||||||
[xAxis]="xAxis"
|
|
||||||
[yAxis]="yAxis"
|
|
||||||
[legend]="legend"
|
|
||||||
[legendTitle]="legendTitle"
|
|
||||||
[showXAxisLabel]="showXAxisLabel"
|
|
||||||
[showYAxisLabel]="showYAxisLabel"
|
|
||||||
[yAxisLabel]="yAxisRevive"
|
|
||||||
[autoScale]="autoscale"
|
|
||||||
[timeline]="timeline"
|
|
||||||
[roundDomains]="roundDomains">
|
|
||||||
</ngx-charts-line-chart>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="chart-container">
|
|
||||||
<ngx-charts-line-chart
|
|
||||||
[results]="captureData"
|
|
||||||
[showRefLines]="showRefLines"
|
|
||||||
[showRefLabels]="showRefLabels"
|
|
||||||
[referenceLines]="captureRefLines"
|
|
||||||
[scheme]="colorScheme"
|
|
||||||
[gradient]="gradient"
|
|
||||||
[xAxis]="xAxis"
|
|
||||||
[yAxis]="yAxis"
|
|
||||||
[legend]="legend"
|
|
||||||
[legendTitle]="legendTitle"
|
|
||||||
[showXAxisLabel]="showXAxisLabel"
|
|
||||||
[showYAxisLabel]="showYAxisLabel"
|
|
||||||
[yAxisLabel]="yAxisCapture"
|
|
||||||
[autoScale]="autoscale"
|
|
||||||
[timeline]="timeline"
|
|
||||||
[roundDomains]="roundDomains">
|
|
||||||
</ngx-charts-line-chart>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,8 +2,6 @@ import {Component} from "@angular/core";
|
||||||
import {ActivatedRoute} from "@angular/router";
|
import {ActivatedRoute} from "@angular/router";
|
||||||
import {CampaignPlayer} from "../../models/model-interfaces";
|
import {CampaignPlayer} from "../../models/model-interfaces";
|
||||||
import {PlayerService} from "../../services/player-service/player.service";
|
import {PlayerService} from "../../services/player-service/player.service";
|
||||||
import {ChartUtils} from "../../utils/chart-utils";
|
|
||||||
import {Location} from '@angular/common';
|
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -13,165 +11,22 @@ import {Location} from '@angular/common';
|
||||||
})
|
})
|
||||||
export class CampaignPlayerDetailComponent {
|
export class CampaignPlayerDetailComponent {
|
||||||
|
|
||||||
campaignPlayer: CampaignPlayer = {campaign: {}, players: []};
|
campaignPlayer: CampaignPlayer = {};
|
||||||
|
|
||||||
sumData: any[] = [];
|
fractionRadioSelect: string;
|
||||||
killData: any[] = [];
|
|
||||||
friendlyFireData: any[] = [];
|
|
||||||
deathData: any[] = [];
|
|
||||||
respawnData: any[] = [];
|
|
||||||
reviveData: any[] = [];
|
|
||||||
captureData: any[] = [];
|
|
||||||
|
|
||||||
yAxisKill = 'Kills';
|
|
||||||
yAxisFriendlyFire = 'FriendlyFire';
|
|
||||||
yAxisDeath = 'Tode';
|
|
||||||
yAxisRespawn = 'Respawn';
|
|
||||||
yAxisRevive = 'Revive';
|
|
||||||
yAxisCapture = 'Eroberungen';
|
|
||||||
avgLabel = 'Durchschnitt';
|
|
||||||
|
|
||||||
colorScheme = {
|
|
||||||
domain: ['#00ce12']
|
|
||||||
};
|
|
||||||
colorSchemeBar = {
|
|
||||||
domain: [
|
|
||||||
'#2d5a00', '#455600', '#00561f', '#3f3b00', '#003c19', '#083c00'
|
|
||||||
]
|
|
||||||
};
|
|
||||||
showRefLines = true;
|
|
||||||
showRefLabels = true;
|
|
||||||
killRefLines = [];
|
|
||||||
deathRefLines = [];
|
|
||||||
captureRefLines = [];
|
|
||||||
friendlyFireRefLines = [];
|
|
||||||
reviveRefLines = [];
|
|
||||||
respawnRefLines = [];
|
|
||||||
|
|
||||||
gradient = false;
|
|
||||||
xAxis = true;
|
|
||||||
yAxis = true;
|
|
||||||
legend = false;
|
|
||||||
legendTitle = '';
|
|
||||||
showXAxisLabel = true;
|
|
||||||
showYAxisLabel = true;
|
|
||||||
autoscale = false;
|
|
||||||
timeline = false;
|
|
||||||
roundDomains = true;
|
|
||||||
|
|
||||||
totalKills;
|
|
||||||
totalFriendlyFire;
|
|
||||||
totalDeath;
|
|
||||||
totalRespawn;
|
|
||||||
totalRevive;
|
|
||||||
totalCapture;
|
|
||||||
|
|
||||||
kdRatio = 0;
|
|
||||||
maxKd = 1.7;
|
|
||||||
respawnDeathRatio = 0;
|
|
||||||
|
|
||||||
|
|
||||||
constructor(private route: ActivatedRoute,
|
constructor(private route: ActivatedRoute,
|
||||||
private location: Location,
|
|
||||||
private playerService: PlayerService) {
|
private playerService: PlayerService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.route.params
|
this.route.params
|
||||||
.map(params => [params['id'], params['playerName']])
|
.map(params => [params['id'], params['playerName']])
|
||||||
.flatMap(id => this.playerService.getCampaignPlayer(id[0], encodeURIComponent(id[1])))
|
.flatMap(id => this.playerService.getCampaignPlayer(id[0], id[1]))
|
||||||
.subscribe(campaignPlayer => {
|
.subscribe(campaignPlayer => {
|
||||||
this.campaignPlayer = campaignPlayer;
|
this.campaignPlayer = campaignPlayer;
|
||||||
this.killData = this.assignData(this.yAxisKill, "kill");
|
|
||||||
this.friendlyFireData = this.assignData(this.yAxisFriendlyFire, "friendlyFire");
|
|
||||||
this.deathData = this.assignData(this.yAxisDeath, "death");
|
|
||||||
this.respawnData = this.assignData(this.yAxisRespawn, "respawn");
|
|
||||||
this.reviveData = this.assignData(this.yAxisRevive, "revive");
|
|
||||||
this.captureData = this.assignData(this.yAxisCapture, "flagTouch");
|
|
||||||
|
|
||||||
this.kdRatio = parseFloat((this.totalKills / this.totalDeath).toFixed(2));
|
|
||||||
if (this.kdRatio > 1) this.maxKd = this.kdRatio * 1.7;
|
|
||||||
|
|
||||||
this.respawnDeathRatio = parseFloat((this.totalRespawn / this.totalDeath).toFixed(2));
|
|
||||||
|
|
||||||
this.sumData = [
|
|
||||||
{
|
|
||||||
name: this.yAxisKill,
|
|
||||||
value: this.totalKills
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: this.yAxisFriendlyFire,
|
|
||||||
value: this.totalFriendlyFire
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: this.yAxisDeath,
|
|
||||||
value: this.totalDeath
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: this.yAxisRespawn,
|
|
||||||
value: this.totalRespawn
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: this.yAxisRevive,
|
|
||||||
value: this.totalRevive
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: this.yAxisCapture,
|
|
||||||
value: this.totalCapture
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
Object.assign(this, [this.sumData, this.killData, this.friendlyFireData, this.deathData, this.respawnData, this.reviveData, this.captureData]);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private assignData(label, field) {
|
|
||||||
let killObj = {
|
|
||||||
name: label,
|
|
||||||
series: []
|
|
||||||
};
|
|
||||||
const playerLength = this.campaignPlayer.players.length;
|
|
||||||
let total = 0;
|
|
||||||
for (let i = 0; i < playerLength; i++) {
|
|
||||||
const warDateString = ChartUtils.getShortDateString(this.campaignPlayer.players[i].warId.date);
|
|
||||||
const warKills = this.campaignPlayer.players[i][field];
|
|
||||||
killObj.series.push({
|
|
||||||
name: warDateString,
|
|
||||||
value: warKills
|
|
||||||
});
|
|
||||||
total += warKills;
|
|
||||||
}
|
|
||||||
switch (field) {
|
|
||||||
case 'kill':
|
|
||||||
this.killRefLines.push({value: total / playerLength, name: this.avgLabel});
|
|
||||||
this.totalKills = total;
|
|
||||||
break;
|
|
||||||
case 'friendlyFire':
|
|
||||||
this.friendlyFireRefLines.push({value: total / playerLength, name: this.avgLabel});
|
|
||||||
this.totalFriendlyFire = total;
|
|
||||||
break;
|
|
||||||
case 'death':
|
|
||||||
this.deathRefLines.push({value: total / playerLength, name: this.avgLabel});
|
|
||||||
this.totalDeath = total;
|
|
||||||
break;
|
|
||||||
case 'respawn':
|
|
||||||
this.respawnRefLines.push({value: total / playerLength, name: this.avgLabel});
|
|
||||||
this.totalRespawn = total;
|
|
||||||
break;
|
|
||||||
case 'revive':
|
|
||||||
this.reviveRefLines.push({value: total / playerLength, name: this.avgLabel});
|
|
||||||
this.totalRevive = total;
|
|
||||||
break;
|
|
||||||
case 'flagTouch':
|
|
||||||
this.captureRefLines.push({value: total / playerLength, name: this.avgLabel});
|
|
||||||
this.totalCapture = total;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return [killObj];
|
|
||||||
}
|
|
||||||
|
|
||||||
navigateBack() {
|
|
||||||
this.location.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ import {Component} from "@angular/core";
|
||||||
import {ActivatedRoute} from "@angular/router";
|
import {ActivatedRoute} from "@angular/router";
|
||||||
import {CarouselConfig} from "ngx-bootstrap";
|
import {CarouselConfig} from "ngx-bootstrap";
|
||||||
import {CampaignService} from "../../services/campaign-service/campaign.service";
|
import {CampaignService} from "../../services/campaign-service/campaign.service";
|
||||||
import {ChartUtils} from "../../utils/chart-utils";
|
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -95,7 +94,11 @@ export class StatisticOverviewComponent {
|
||||||
|
|
||||||
for (let i = wars.length - 1; i >= 0; i--) {
|
for (let i = wars.length - 1; i >= 0; i--) {
|
||||||
let j = wars.length - i - 1;
|
let j = wars.length - i - 1;
|
||||||
const warDateString = ChartUtils.getShortDateString(wars[i].date);
|
// const warDateString = new Date(wars[i].date); TODO: use ngx-chart timeline
|
||||||
|
const isoDate = wars[i].date.slice(0, 10);
|
||||||
|
const dayDate = parseInt(isoDate.slice(8, 10)) + 1;
|
||||||
|
const warDateString = (dayDate < 10 ? "0" + dayDate : dayDate) + '.'
|
||||||
|
+ isoDate.slice(5, 7) + '.' + isoDate.slice(2, 4);
|
||||||
|
|
||||||
pointsObj[0].series.push({
|
pointsObj[0].series.push({
|
||||||
name: warDateString,
|
name: warDateString,
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {CommonModule} from "@angular/common";
|
||||||
import {SharedModule} from "../shared.module";
|
import {SharedModule} from "../shared.module";
|
||||||
import {statsRouterModule, statsRoutingComponents} from "./stats.routing";
|
import {statsRouterModule, statsRoutingComponents} from "./stats.routing";
|
||||||
import {WarService} from "../services/war-service/war.service";
|
import {WarService} from "../services/war-service/war.service";
|
||||||
import {GaugeModule, LineChartModule, NgxChartsModule, PieChartModule} from "@swimlane/ngx-charts";
|
import {LineChartModule, PieChartModule} from "@swimlane/ngx-charts";
|
||||||
import {AccordionModule, CarouselModule} from "ngx-bootstrap";
|
import {AccordionModule, CarouselModule} from "ngx-bootstrap";
|
||||||
import {CampaignService} from "../services/campaign-service/campaign.service";
|
import {CampaignService} from "../services/campaign-service/campaign.service";
|
||||||
import {NgxDatatableModule} from "@swimlane/ngx-datatable";
|
import {NgxDatatableModule} from "@swimlane/ngx-datatable";
|
||||||
|
@ -11,7 +11,7 @@ import {PlayerService} from "../services/player-service/player.service";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: statsRoutingComponents,
|
declarations: statsRoutingComponents,
|
||||||
imports: [CommonModule, SharedModule, statsRouterModule, NgxChartsModule,
|
imports: [CommonModule, SharedModule, statsRouterModule, LineChartModule, PieChartModule,
|
||||||
AccordionModule.forRoot(), CarouselModule.forRoot(), NgxDatatableModule],
|
AccordionModule.forRoot(), CarouselModule.forRoot(), NgxDatatableModule],
|
||||||
providers: [WarService, CampaignService, PlayerService]
|
providers: [WarService, CampaignService, PlayerService]
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
export class ChartUtils {
|
|
||||||
|
|
||||||
public static getShortDateString(date) : string {
|
|
||||||
const isoDate = date.slice(0, 10);
|
|
||||||
const dayDate = parseInt(isoDate.slice(8, 10)) + 1;
|
|
||||||
return (dayDate < 10 ? "0" + dayDate : dayDate) + '.'
|
|
||||||
+ isoDate.slice(5, 7) + '.' + isoDate.slice(2, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue