27 changed files with 350 additions and 28 deletions
@ -0,0 +1,23 @@ |
|||
export class PlayerProfile { |
|||
ban: any|null = null; |
|||
gametime: {[srv_name: string]: {[map_name: string]: number}} = {}; |
|||
lastplay: {[srv_name: string]: {[map_name: string]: number}} = {}; |
|||
permition: any|null = null; |
|||
response_time: {[request: string]: number} = {}; |
|||
steam_data: any|null = null; |
|||
steamids: any|null = null; |
|||
play_on: any|null = null; |
|||
attached_discords: any[]|null = null; |
|||
donates: any[]|null = null; |
|||
ban_list: any[]|null = null; |
|||
killfeed: any|null = null; |
|||
killfeed_current: any = null; |
|||
messages: any = null; |
|||
reports: any = null; |
|||
|
|||
static fromData(data:any): PlayerProfile { |
|||
const p = new PlayerProfile(); |
|||
Object.assign(p, data); |
|||
return p; |
|||
} |
|||
} |
@ -0,0 +1,25 @@ |
|||
export class ProfileRequestData { |
|||
static PLAY_ON: ProfileRequestData = new ProfileRequestData("play_on", "Проверка играет ли сейчас"); |
|||
static STEAM_DATA: ProfileRequestData = new ProfileRequestData("steam_data", "Данные стима"); |
|||
static LAST_PLAY: ProfileRequestData = new ProfileRequestData("lastplay", "Последняя игра"); |
|||
static USER_TIME: ProfileRequestData = new ProfileRequestData("usertime", "Количество наигранного времени"); |
|||
static PERMITION: ProfileRequestData = new ProfileRequestData("permition", "Получить данные о правах"); |
|||
static BAN: ProfileRequestData = new ProfileRequestData("ban", "Получение текущего бана"); |
|||
static ATTACHED_DISCORD: ProfileRequestData = new ProfileRequestData("attached_discord", "Привязка к дискорду"); |
|||
static DONATES: ProfileRequestData = new ProfileRequestData("donates", "Получения данных о донатах"); |
|||
static BAN_LIST: ProfileRequestData = new ProfileRequestData("ban_list", "Получить список банов от пельменя"); |
|||
static KILLFEED: ProfileRequestData = new ProfileRequestData("killfeed", "Информация о убийствах, смертях, помощи"); |
|||
static REPORTS: ProfileRequestData = new ProfileRequestData("reports", "Информация о количестве репортах"); |
|||
static MESSAGES: ProfileRequestData = new ProfileRequestData("messages", "Информация о количестве сообщений"); |
|||
|
|||
param: string; |
|||
description: string; |
|||
default: boolean; |
|||
|
|||
|
|||
constructor(request_parameter: string, description_text: string) { |
|||
this.param = request_parameter; |
|||
this.description = description_text; |
|||
this.default = false; |
|||
} |
|||
} |
@ -0,0 +1,7 @@ |
|||
export interface DockerStats { |
|||
cpu: {percent: number}; |
|||
io: {input: number, output: number}; |
|||
mem: {percent: number, usage: number, limit: number}; |
|||
net: {input:number, output: number}; |
|||
utime: number; |
|||
} |
@ -0,0 +1,15 @@ |
|||
export interface Player { |
|||
clz: number|null; |
|||
deads: number; |
|||
duration_seconds: number; |
|||
id: number; |
|||
loss: number; |
|||
name: string; |
|||
ping: number; |
|||
pos: number[]; |
|||
score: number; |
|||
state: string; |
|||
steam: any; |
|||
steam2: string; |
|||
team: number; |
|||
} |
@ -0,0 +1,22 @@ |
|||
import {DockerStats} from "./DockerStats"; |
|||
import {Uniq} from "./Uniq"; |
|||
import {Player} from "./Player"; |
|||
|
|||
export interface Server { |
|||
address: string; |
|||
city_pos: number[]; |
|||
color: string; |
|||
description: string; |
|||
dockerStats: DockerStats; |
|||
last_update: number; |
|||
map: string; |
|||
max_players: number; |
|||
name: string; |
|||
naming: string[]; |
|||
player_count: number; |
|||
players: Player[]; |
|||
preview: string; |
|||
status: boolean; |
|||
uniq: Uniq; |
|||
workshop: string|null; |
|||
} |
@ -0,0 +1,6 @@ |
|||
export interface Uniq { |
|||
day: number; |
|||
month: number; |
|||
year: number; |
|||
total: number; |
|||
} |
@ -0,0 +1,7 @@ |
|||
<div class="content-in-center-header" style="flex-direction: column;"> |
|||
<h1>Вася убийца 2007</h1> |
|||
<h3>бибики</h3> |
|||
</div> |
|||
|
|||
<div class="content-in-center"> |
|||
</div> |
@ -0,0 +1,31 @@ |
|||
import { Component, OnInit } from '@angular/core'; |
|||
import {ActivatedRoute} from "@angular/router"; |
|||
import {PlayerServiceService} from "../../services/player-service.service"; |
|||
import {PlayerProfile} from "../../entities/profile/PlayerProfile"; |
|||
import {MatSnackBar} from "@angular/material/snack-bar"; |
|||
|
|||
@Component({ |
|||
selector: 'app-profile-page', |
|||
templateUrl: './profile-page.component.html', |
|||
styleUrls: ['./profile-page.component.scss'] |
|||
}) |
|||
export class ProfilePageComponent implements OnInit { |
|||
|
|||
profile: PlayerProfile|null = null; |
|||
|
|||
constructor(private route: ActivatedRoute, |
|||
private playerService: PlayerServiceService, |
|||
private snack: MatSnackBar) { } |
|||
|
|||
ngOnInit(): void { |
|||
const steam64: string|null = this.route.snapshot.queryParamMap.get("steam64"); |
|||
this.loadPlayer(steam64); |
|||
} |
|||
|
|||
loadPlayer(steam64: string|null) { |
|||
this.playerService.getProfile(steam64, []).subscribe( |
|||
(res) => this.profile = res, |
|||
(err) => this.snack.open("Невозможно загрузить профиль") |
|||
); |
|||
} |
|||
} |
@ -0,0 +1,35 @@ |
|||
<div class="content-in-center-header" style="flex-direction: column;"> |
|||
<h1>Серверы</h1> |
|||
<h3>Информация о игроках и живых серверах</h3> |
|||
</div> |
|||
|
|||
<div class="content-in-center"> |
|||
<mat-accordion> |
|||
<mat-expansion-panel hideToggle *ngFor="let server of servers | keyvalue"> |
|||
<mat-expansion-panel-header> |
|||
<mat-panel-title> |
|||
{{server.value.name}} |
|||
</mat-panel-title> |
|||
<mat-panel-description> |
|||
{{server.value.player_count}}/{{server.value.max_players}} |
|||
</mat-panel-description> |
|||
</mat-expansion-panel-header> |
|||
<div> |
|||
<p>{{server.value.description}}</p> |
|||
<mat-expansion-panel hideToggle *ngFor="let player of server.value.players"> |
|||
<mat-expansion-panel-header> |
|||
<mat-panel-title> |
|||
{{player.name}} |
|||
</mat-panel-title> |
|||
<mat-panel-description> |
|||
{{player.score}} / {{player.deads}} / {{player.duration_seconds}} |
|||
</mat-panel-description> |
|||
</mat-expansion-panel-header> |
|||
<p>Ид игрока: {{player.id}}</p> |
|||
<p>Пинг: {{player.ping}}</p> |
|||
<p>Потери пакетов: {{player.loss}}</p> |
|||
</mat-expansion-panel> |
|||
</div> |
|||
</mat-expansion-panel> |
|||
</mat-accordion> |
|||
</div> |
@ -0,0 +1,27 @@ |
|||
import { Component, OnInit } from '@angular/core'; |
|||
import {WebsocketServersListenerService} from "../../services/websocket-servers-listener.service"; |
|||
import {Server} from "../../entities/servers/Server"; |
|||
|
|||
@Component({ |
|||
selector: 'app-servers-page', |
|||
templateUrl: './servers-page.component.html', |
|||
styleUrls: ['./servers-page.component.scss'] |
|||
}) |
|||
export class ServersPageComponent implements OnInit { |
|||
|
|||
servers:{[srv_name: string]:Server} = {}; |
|||
|
|||
constructor(private servers_ws:WebsocketServersListenerService) { } |
|||
|
|||
ngOnInit(): void { |
|||
this.servers_ws.getServers().subscribe((r) => { |
|||
if (r.state == 0) this.servers = r.servers; |
|||
else { |
|||
for (let srv_name of Object.keys(r.servers)) { |
|||
Object.assign(this.servers[srv_name], r.servers[srv_name]); |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,6 @@ |
|||
import {Server} from "../entities/servers/Server"; |
|||
|
|||
export interface WebSockerServerMessage { |
|||
servers: {[srv_name: string]:Server}; |
|||
state: 0|1; |
|||
} |
@ -0,0 +1,22 @@ |
|||
import { Injectable } from '@angular/core'; |
|||
import {HttpClient} from "@angular/common/http"; |
|||
import {ProfileRequestData} from "../entities/profile/ProfileRequestData"; |
|||
import * as http from "http"; |
|||
import {map, Observable} from "rxjs"; |
|||
import {PlayerProfile} from "../entities/profile/PlayerProfile"; |
|||
|
|||
@Injectable({ |
|||
providedIn: 'root' |
|||
}) |
|||
export class PlayerServiceService { |
|||
|
|||
constructor(private http: HttpClient) {} |
|||
|
|||
getProfile(steam64: string|null, request: ProfileRequestData[]): Observable<PlayerProfile> { |
|||
const params = { |
|||
requests: request.map((p) => p.param) |
|||
} |
|||
return this.http.get("api/profile/" + steam64 == null ? 'current' : 'web', {params: params}) |
|||
.pipe(map((r) => PlayerProfile.fromData(r))); |
|||
} |
|||
} |
@ -0,0 +1,20 @@ |
|||
import { Injectable } from '@angular/core'; |
|||
import {WebSocketSubject} from "rxjs/internal/observable/dom/WebSocketSubject"; |
|||
import {webSocket} from "rxjs/webSocket"; |
|||
import {map, Observable} from "rxjs"; |
|||
import {WebSockerServerMessage} from "./WebSockerServerMessage"; |
|||
|
|||
@Injectable({ |
|||
providedIn: 'root' |
|||
}) |
|||
export class WebsocketServersListenerService { |
|||
private socket: WebSocketSubject<any>; |
|||
|
|||
constructor() { |
|||
this.socket = webSocket('wss://tf2.pblr-nyk.pro/ws/servers'); |
|||
} |
|||
|
|||
getServers(): Observable<WebSockerServerMessage> { |
|||
return this.socket.asObservable() |
|||
} |
|||
} |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue