8 changed files with 392 additions and 55 deletions
@ -0,0 +1,226 @@ |
|||
import {AfterViewInit, Component, Input, OnInit} from "@angular/core"; |
|||
import {SearchFilter} from "../../entities/search/SearchFilter"; |
|||
import {GraphService, PerPeriodStatistic} from "../../services/graph.service"; |
|||
import {Chart} from "chart.js/auto"; |
|||
import {MatSnackBar} from "@angular/material/snack-bar"; |
|||
import {ServerService} from "../../services/server.service"; |
|||
import {BaseUtils} from "../../utils/BaseUtils"; |
|||
|
|||
@Component({ |
|||
selector: "app-usertime-graph", |
|||
template: ` |
|||
<div> |
|||
<mat-radio-group |
|||
style="display: flex; justify-content: center;flex-direction: row;" |
|||
[(ngModel)]="usertimeChart.period" |
|||
[disabled]="usertimeChart.loading" |
|||
(ngModelChange)="updateUsertimeGraph()"> |
|||
<mat-radio-button style="padding-right: 1%; padding-left: 1%" value="day">За месяц</mat-radio-button> |
|||
<mat-radio-button style="padding-right: 1%; padding-left: 1%" value="month">За год</mat-radio-button> |
|||
<mat-radio-button style="padding-right: 1%; padding-left: 1%" value="year">За 10 лет</mat-radio-button> |
|||
</mat-radio-group> |
|||
</div> |
|||
<div class="chart-container"> |
|||
<canvas id="usertimeChart" >{{ usertimeChart.chart }}</canvas> |
|||
</div>` |
|||
}) |
|||
export class UsertimeGraphComponent implements OnInit { |
|||
|
|||
usertimeChart: { |
|||
chart: Chart|null |
|||
period: 'day' | 'month' | 'year', |
|||
loading: boolean |
|||
} = { |
|||
chart: null, |
|||
period: "day", |
|||
loading: false |
|||
}; |
|||
|
|||
@Input("steam64") |
|||
steam64: string|null = null; |
|||
serverList: {name: string, server_id: string }[] = []; |
|||
timeDelimiter: number = 1; |
|||
|
|||
tooltipFooter = (items:any) => { |
|||
return "Наиграно: " + BaseUtils.formatSeconds(items.pop().parsed.y * this.timeDelimiter); |
|||
}; |
|||
|
|||
constructor(protected serverService: ServerService, |
|||
private graphService: GraphService, |
|||
private snack: MatSnackBar) { |
|||
} |
|||
|
|||
ngOnInit(): void { |
|||
const fill = (res:any) => { |
|||
const keys = res.data ? Object.keys(res.data) : []; |
|||
for (const key of keys) { |
|||
// @ts-ignore
|
|||
this.serverList.push({name: res.data[key].name, server_id: key}); |
|||
} |
|||
} |
|||
|
|||
this.serverService.getServers().subscribe( |
|||
(res) => { |
|||
fill(res); |
|||
} |
|||
) |
|||
} |
|||
|
|||
getServerName(server_id: string|null) { |
|||
try { |
|||
// @ts-ignore
|
|||
return this.serverList.filter(s => s.server_id == server_id).pop().name; |
|||
} catch (e) { |
|||
return "Неизвестно"; |
|||
} |
|||
} |
|||
|
|||
usertimeTabChanged(event: any) { |
|||
if (event.index == 1) { |
|||
this.updateUsertimeGraph() |
|||
} |
|||
} |
|||
|
|||
updateUsertimeGraph() { |
|||
if (this.steam64 || true) { |
|||
if (this.usertimeChart.loading) return; |
|||
this.usertimeChart.loading = true; |
|||
|
|||
const filter: SearchFilter = new SearchFilter(); |
|||
if (this.steam64) |
|||
filter.addAccountToSearch(this.steam64); |
|||
let endDate = new Date(); |
|||
endDate.setUTCHours(23, 59, 59); |
|||
filter.addEndTimeToSearch(endDate.getTime()); |
|||
switch (this.usertimeChart.period) { |
|||
case "day": { |
|||
endDate.setDate(endDate.getDate() - 30); |
|||
break; |
|||
} |
|||
case "month": { |
|||
endDate.setDate(endDate.getDate() - 365); |
|||
break; |
|||
} |
|||
case "year": { |
|||
endDate.setDate(endDate.getDate() - (365*10)); |
|||
break; |
|||
} |
|||
} |
|||
filter.addBeginTimeToSearch(endDate); |
|||
let chartConfig = {type: 'bar', data: {}, options: { |
|||
plugins: { |
|||
title: { |
|||
display: true, |
|||
text: "Наиграно секунд по серверам" |
|||
}, |
|||
tooltip:{ |
|||
callbacks: { |
|||
footer: this.tooltipFooter |
|||
} |
|||
} |
|||
}, |
|||
responsive: true, |
|||
scales: { |
|||
x: { |
|||
stacked: true, |
|||
}, |
|||
y: { |
|||
stacked: true |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
let chartData: {labels: string[], datasets: any[]} = { |
|||
labels: [],//даты
|
|||
datasets: [] |
|||
/** |
|||
* { |
|||
* label: 'Dataset 1', |
|||
* data: Utils.numbers(NUMBER_CFG), |
|||
* backgroundColor: Utils.CHART_COLORS.red, |
|||
* }, |
|||
*/ |
|||
}; |
|||
let valueOnServer: {[srv_name: string]: number[]} = {} |
|||
let srvList: string[] = []; |
|||
|
|||
let maxValue = 0; |
|||
|
|||
this.graphService.getUsertimeOnPeriod(filter).subscribe( |
|||
(objs) => { |
|||
objs.forEach((obj) => {if (obj.value > maxValue) maxValue = obj.value}) |
|||
if (maxValue >= 60) { |
|||
this.timeDelimiter = 60; |
|||
chartConfig.options.plugins.title.text = "Наиграно минут по серверам"; |
|||
} //po minutam
|
|||
if (maxValue >= 60 * 60) { |
|||
this.timeDelimiter = 60 * 60; |
|||
chartConfig.options.plugins.title.text = "Наиграно часов по серверам"; |
|||
} //po chasam
|
|||
if (maxValue >= 60 * 60 * 24) { |
|||
this.timeDelimiter = 60 * 60 * 24; |
|||
chartConfig.options.plugins.title.text = "Наиграно дней по серверам"; |
|||
}//po dnyam
|
|||
|
|||
const groupByDate = objs.reduce((acc: {[date: string]: PerPeriodStatistic[]}, obj) => { |
|||
const key = obj.date; |
|||
if (!acc[key]) acc[key] = []; |
|||
acc[key].push(obj) |
|||
return acc; |
|||
}, {}); |
|||
chartData.labels = Object.keys(groupByDate); |
|||
//console.log(groupByDate);
|
|||
|
|||
chartData.labels.forEach( |
|||
(date) => { |
|||
groupByDate[date].forEach((stat) => { |
|||
if (srvList.indexOf(stat.srv_id) == -1) |
|||
srvList.push(stat.srv_id) |
|||
}) |
|||
} |
|||
); |
|||
//console.log(srvList)
|
|||
srvList.forEach((srv) => { |
|||
valueOnServer[srv] = []; |
|||
}); |
|||
chartData.labels.forEach( |
|||
(date) => { |
|||
let filled: string[] = []; |
|||
groupByDate[date].forEach( |
|||
(obj) => { |
|||
valueOnServer[obj.srv_id].push(obj.value / this.timeDelimiter) |
|||
filled.push(obj.srv_id); |
|||
} |
|||
) |
|||
srvList.forEach( |
|||
(srv) => { |
|||
if (filled.indexOf(srv) == -1) { |
|||
valueOnServer[srv].push(0); |
|||
} |
|||
} |
|||
) |
|||
}, |
|||
) |
|||
//console.log(valueOnServer)
|
|||
Object.keys(valueOnServer).forEach( |
|||
(key) => { |
|||
chartData.datasets.push( |
|||
{label: this.getServerName(key) + " ("+key+")", data: valueOnServer[key]} |
|||
) |
|||
} |
|||
) |
|||
///
|
|||
chartConfig.data = chartData; |
|||
|
|||
if (this.usertimeChart.chart) |
|||
this.usertimeChart.chart.destroy(); |
|||
// @ts-ignore
|
|||
this.usertimeChart.chart = new Chart('usertimeChart', chartConfig); |
|||
this.usertimeChart.loading = false; |
|||
}, (err) => {this.usertimeChart.loading = false; this.snack.open("Ошибка загрузка графика")} |
|||
); |
|||
} else { |
|||
this.snack.open("Нельзя загрузить график т.к нельзя определить индификатор профиля"); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue