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