mirror of
https://codeberg.org/demostf/api.git
synced 2026-06-04 02:14:06 +02:00
Add php-cs-fixer
This commit is contained in:
parent
e00e6ece5f
commit
309ae17036
54 changed files with 4900 additions and 4106 deletions
|
|
@ -1,46 +1,46 @@
|
|||
<?php namespace Demostf\API\Demo;
|
||||
|
||||
class ChatMessage {
|
||||
/** @var string */
|
||||
private $user;
|
||||
/** @var string */
|
||||
private $user;
|
||||
|
||||
/** @var integer */
|
||||
private $time;
|
||||
/** @var integer */
|
||||
private $time;
|
||||
|
||||
/** @var string */
|
||||
private $message;
|
||||
/** @var string */
|
||||
private $message;
|
||||
|
||||
/**
|
||||
* ChatMessage constructor.
|
||||
*
|
||||
* @param string $user
|
||||
* @param int $time
|
||||
* @param string $message
|
||||
*/
|
||||
public function __construct(string $user, int $time, string $message) {
|
||||
$this->user = $user;
|
||||
$this->time = $time;
|
||||
$this->message = $message;
|
||||
}
|
||||
/**
|
||||
* ChatMessage constructor.
|
||||
*
|
||||
* @param string $user
|
||||
* @param int $time
|
||||
* @param string $message
|
||||
*/
|
||||
public function __construct(string $user, int $time, string $message) {
|
||||
$this->user = $user;
|
||||
$this->time = $time;
|
||||
$this->message = $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getUser(): string {
|
||||
return $this->user;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getUser(): string {
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getTime(): int {
|
||||
return $this->time;
|
||||
}
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getTime(): int {
|
||||
return $this->time;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMessage(): string {
|
||||
return $this->message;
|
||||
}
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMessage(): string {
|
||||
return $this->message;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,215 +4,215 @@ use Demostf\API\Data\DemoPlayer;
|
|||
use Demostf\API\Data\User;
|
||||
|
||||
class Demo implements \JsonSerializable {
|
||||
/** @var int */
|
||||
private $id;
|
||||
/** @var string */
|
||||
private $url;
|
||||
/** @var string */
|
||||
private $name;
|
||||
/** @var string */
|
||||
private $server;
|
||||
/** @var float */
|
||||
private $duration;
|
||||
/** @var string */
|
||||
private $nick;
|
||||
/** @var string */
|
||||
private $map;
|
||||
/** @var \DateTime */
|
||||
private $time;
|
||||
/** @var string */
|
||||
private $red;
|
||||
/** @var string */
|
||||
private $blue;
|
||||
/** @var int */
|
||||
private $redScore;
|
||||
/** @var int */
|
||||
private $blueScore;
|
||||
/** @var int */
|
||||
private $playerCount;
|
||||
/** @var int */
|
||||
private $uploader;
|
||||
/** @var User|null */
|
||||
private $uploaderUser;
|
||||
/** @var DemoPlayer[] */
|
||||
private $players;
|
||||
/** @var string */
|
||||
private $hash;
|
||||
/** @var string */
|
||||
private $backend;
|
||||
/** @var string */
|
||||
private $path;
|
||||
/** @var int */
|
||||
private $id;
|
||||
/** @var string */
|
||||
private $url;
|
||||
/** @var string */
|
||||
private $name;
|
||||
/** @var string */
|
||||
private $server;
|
||||
/** @var float */
|
||||
private $duration;
|
||||
/** @var string */
|
||||
private $nick;
|
||||
/** @var string */
|
||||
private $map;
|
||||
/** @var \DateTime */
|
||||
private $time;
|
||||
/** @var string */
|
||||
private $red;
|
||||
/** @var string */
|
||||
private $blue;
|
||||
/** @var int */
|
||||
private $redScore;
|
||||
/** @var int */
|
||||
private $blueScore;
|
||||
/** @var int */
|
||||
private $playerCount;
|
||||
/** @var int */
|
||||
private $uploader;
|
||||
/** @var User|null */
|
||||
private $uploaderUser;
|
||||
/** @var DemoPlayer[] */
|
||||
private $players;
|
||||
/** @var string */
|
||||
private $hash;
|
||||
/** @var string */
|
||||
private $backend;
|
||||
/** @var string */
|
||||
private $path;
|
||||
|
||||
public function __construct(
|
||||
int $id,
|
||||
string $url,
|
||||
string $name,
|
||||
string $server,
|
||||
float $duration,
|
||||
string $nick,
|
||||
string $map,
|
||||
\DateTime $time,
|
||||
string $red,
|
||||
string $blue,
|
||||
int $redScore,
|
||||
int $blueScore,
|
||||
int $playerCount,
|
||||
int $uploader,
|
||||
string $hash,
|
||||
string $backend,
|
||||
string $path
|
||||
) {
|
||||
$this->id = $id;
|
||||
$this->url = $url;
|
||||
$this->name = $name;
|
||||
$this->server = $server;
|
||||
$this->duration = $duration;
|
||||
$this->nick = $nick;
|
||||
$this->map = $map;
|
||||
$this->time = $time;
|
||||
$this->red = $red;
|
||||
$this->blue = $blue;
|
||||
$this->redScore = $redScore;
|
||||
$this->blueScore = $blueScore;
|
||||
$this->playerCount = $playerCount;
|
||||
$this->uploader = $uploader;
|
||||
$this->hash = $hash;
|
||||
$this->backend = $backend;
|
||||
$this->path = $path;
|
||||
}
|
||||
public function __construct(
|
||||
int $id,
|
||||
string $url,
|
||||
string $name,
|
||||
string $server,
|
||||
float $duration,
|
||||
string $nick,
|
||||
string $map,
|
||||
\DateTime $time,
|
||||
string $red,
|
||||
string $blue,
|
||||
int $redScore,
|
||||
int $blueScore,
|
||||
int $playerCount,
|
||||
int $uploader,
|
||||
string $hash,
|
||||
string $backend,
|
||||
string $path
|
||||
) {
|
||||
$this->id = $id;
|
||||
$this->url = $url;
|
||||
$this->name = $name;
|
||||
$this->server = $server;
|
||||
$this->duration = $duration;
|
||||
$this->nick = $nick;
|
||||
$this->map = $map;
|
||||
$this->time = $time;
|
||||
$this->red = $red;
|
||||
$this->blue = $blue;
|
||||
$this->redScore = $redScore;
|
||||
$this->blueScore = $blueScore;
|
||||
$this->playerCount = $playerCount;
|
||||
$this->uploader = $uploader;
|
||||
$this->hash = $hash;
|
||||
$this->backend = $backend;
|
||||
$this->path = $path;
|
||||
}
|
||||
|
||||
public function getId(): int {
|
||||
return $this->id;
|
||||
}
|
||||
public function getId(): int {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getUrl(): string {
|
||||
return $this->url;
|
||||
}
|
||||
public function getUrl(): string {
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
public function getName(): string {
|
||||
return $this->name;
|
||||
}
|
||||
public function getName(): string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getServer(): string {
|
||||
return $this->server;
|
||||
}
|
||||
public function getServer(): string {
|
||||
return $this->server;
|
||||
}
|
||||
|
||||
public function getDuration(): float {
|
||||
return $this->duration;
|
||||
}
|
||||
public function getDuration(): float {
|
||||
return $this->duration;
|
||||
}
|
||||
|
||||
public function getNick(): string {
|
||||
return $this->nick;
|
||||
}
|
||||
public function getNick(): string {
|
||||
return $this->nick;
|
||||
}
|
||||
|
||||
public function getMap(): string {
|
||||
return $this->map;
|
||||
}
|
||||
public function getMap(): string {
|
||||
return $this->map;
|
||||
}
|
||||
|
||||
public function getTime(): \DateTime {
|
||||
return $this->time;
|
||||
}
|
||||
public function getTime(): \DateTime {
|
||||
return $this->time;
|
||||
}
|
||||
|
||||
public function getRed(): string {
|
||||
return $this->red;
|
||||
}
|
||||
public function getRed(): string {
|
||||
return $this->red;
|
||||
}
|
||||
|
||||
public function getBlue(): string {
|
||||
return $this->blue;
|
||||
}
|
||||
public function getBlue(): string {
|
||||
return $this->blue;
|
||||
}
|
||||
|
||||
public function getRedScore(): int {
|
||||
return $this->redScore;
|
||||
}
|
||||
public function getRedScore(): int {
|
||||
return $this->redScore;
|
||||
}
|
||||
|
||||
public function getBlueScore(): int {
|
||||
return $this->blueScore;
|
||||
}
|
||||
public function getBlueScore(): int {
|
||||
return $this->blueScore;
|
||||
}
|
||||
|
||||
public function getPlayerCount(): int {
|
||||
return $this->playerCount;
|
||||
}
|
||||
public function getPlayerCount(): int {
|
||||
return $this->playerCount;
|
||||
}
|
||||
|
||||
public function getUploader(): int {
|
||||
return $this->uploader;
|
||||
}
|
||||
public function getUploader(): int {
|
||||
return $this->uploader;
|
||||
}
|
||||
|
||||
public function getUploaderUser(): ?User {
|
||||
return $this->uploaderUser;
|
||||
}
|
||||
public function getUploaderUser(): ?User {
|
||||
return $this->uploaderUser;
|
||||
}
|
||||
|
||||
public function setUploaderUser(User $uploaderUser) {
|
||||
$this->uploaderUser = $uploaderUser;
|
||||
}
|
||||
public function setUploaderUser(User $uploaderUser) {
|
||||
$this->uploaderUser = $uploaderUser;
|
||||
}
|
||||
|
||||
public static function fromRow($row): Demo {
|
||||
return new Demo(
|
||||
(int)$row['id'],
|
||||
$row['url'],
|
||||
$row['name'],
|
||||
$row['server'],
|
||||
(int)$row['duration'],
|
||||
$row['nick'],
|
||||
$row['map'],
|
||||
\DateTime::createFromFormat('U', '' . strtotime($row['created_at'])),
|
||||
$row['red'],
|
||||
$row['blu'],
|
||||
(int)$row['scoreRed'],
|
||||
(int)$row['scoreBlue'],
|
||||
(int)$row['playerCount'],
|
||||
(int)$row['uploader'],
|
||||
$row['hash'],
|
||||
$row['backend'],
|
||||
$row['path']
|
||||
);
|
||||
}
|
||||
public static function fromRow($row): Demo {
|
||||
return new Demo(
|
||||
(int)$row['id'],
|
||||
$row['url'],
|
||||
$row['name'],
|
||||
$row['server'],
|
||||
(int)$row['duration'],
|
||||
$row['nick'],
|
||||
$row['map'],
|
||||
\DateTime::createFromFormat('U', '' . strtotime($row['created_at'])),
|
||||
$row['red'],
|
||||
$row['blu'],
|
||||
(int)$row['scoreRed'],
|
||||
(int)$row['scoreBlue'],
|
||||
(int)$row['playerCount'],
|
||||
(int)$row['uploader'],
|
||||
$row['hash'],
|
||||
$row['backend'],
|
||||
$row['path']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DemoPlayer[]
|
||||
*/
|
||||
public function getPlayers(): array {
|
||||
return $this->players;
|
||||
}
|
||||
/**
|
||||
* @return DemoPlayer[]
|
||||
*/
|
||||
public function getPlayers(): array {
|
||||
return $this->players;
|
||||
}
|
||||
|
||||
public function setPlayers(array $players) {
|
||||
$this->players = $players;
|
||||
}
|
||||
public function setPlayers(array $players) {
|
||||
$this->players = $players;
|
||||
}
|
||||
|
||||
public function getHash(): string {
|
||||
return $this->hash;
|
||||
}
|
||||
public function getHash(): string {
|
||||
return $this->hash;
|
||||
}
|
||||
|
||||
public function getBackend(): string {
|
||||
return $this->backend;
|
||||
}
|
||||
public function getBackend(): string {
|
||||
return $this->backend;
|
||||
}
|
||||
|
||||
public function getPath(): string {
|
||||
return $this->path;
|
||||
}
|
||||
public function getPath(): string {
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
public function jsonSerialize() {
|
||||
$data = [
|
||||
'id' => $this->getId(),
|
||||
'url' => $this->getUrl(),
|
||||
'name' => $this->getName(),
|
||||
'server' => $this->getServer(),
|
||||
'duration' => $this->getDuration(),
|
||||
'nick' => $this->getNick(),
|
||||
'map' => $this->getMap(),
|
||||
'time' => $this->getTime()->getTimestamp(),
|
||||
'red' => $this->getRed(),
|
||||
'blue' => $this->getBlue(),
|
||||
'redScore' => $this->getRedScore(),
|
||||
'blueScore' => $this->getBlueScore(),
|
||||
'playerCount' => $this->getPlayerCount(),
|
||||
'uploader' => $this->uploaderUser ? $this->getUploaderUser()->jsonSerialize() : $this->getUploader(),
|
||||
'hash' => $this->getHash(),
|
||||
'backend' => $this->getBackend(),
|
||||
'path' => $this->getPath()
|
||||
];
|
||||
if ($this->players) {
|
||||
$data['players'] = $this->getPlayers();
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
public function jsonSerialize() {
|
||||
$data = [
|
||||
'id' => $this->getId(),
|
||||
'url' => $this->getUrl(),
|
||||
'name' => $this->getName(),
|
||||
'server' => $this->getServer(),
|
||||
'duration' => $this->getDuration(),
|
||||
'nick' => $this->getNick(),
|
||||
'map' => $this->getMap(),
|
||||
'time' => $this->getTime()->getTimestamp(),
|
||||
'red' => $this->getRed(),
|
||||
'blue' => $this->getBlue(),
|
||||
'redScore' => $this->getRedScore(),
|
||||
'blueScore' => $this->getBlueScore(),
|
||||
'playerCount' => $this->getPlayerCount(),
|
||||
'uploader' => $this->uploaderUser ? $this->getUploaderUser()->jsonSerialize() : $this->getUploader(),
|
||||
'hash' => $this->getHash(),
|
||||
'backend' => $this->getBackend(),
|
||||
'path' => $this->getPath()
|
||||
];
|
||||
if ($this->players) {
|
||||
$data['players'] = $this->getPlayers();
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,79 +14,79 @@ use Demostf\API\Providers\PlayerProvider;
|
|||
use Demostf\API\Providers\UserProvider;
|
||||
|
||||
class DemoSaver {
|
||||
/** @var KillProvider */
|
||||
private $killProvider;
|
||||
/** @var PlayerProvider */
|
||||
private $playerProvider;
|
||||
/** @var ChatProvider */
|
||||
private $chatProvider;
|
||||
/** @var UserProvider */
|
||||
private $userProvider;
|
||||
/** @var DemoProvider */
|
||||
private $demoProvider;
|
||||
/** @var KillProvider */
|
||||
private $killProvider;
|
||||
/** @var PlayerProvider */
|
||||
private $playerProvider;
|
||||
/** @var ChatProvider */
|
||||
private $chatProvider;
|
||||
/** @var UserProvider */
|
||||
private $userProvider;
|
||||
/** @var DemoProvider */
|
||||
private $demoProvider;
|
||||
|
||||
public function __construct(KillProvider $killProvider, PlayerProvider $playerProvider, ChatProvider $chatProvider, UserProvider $userProvider, DemoProvider $demoProvider) {
|
||||
$this->killProvider = $killProvider;
|
||||
$this->playerProvider = $playerProvider;
|
||||
$this->chatProvider = $chatProvider;
|
||||
$this->userProvider = $userProvider;
|
||||
$this->demoProvider = $demoProvider;
|
||||
}
|
||||
public function __construct(KillProvider $killProvider, PlayerProvider $playerProvider, ChatProvider $chatProvider, UserProvider $userProvider, DemoProvider $demoProvider) {
|
||||
$this->killProvider = $killProvider;
|
||||
$this->playerProvider = $playerProvider;
|
||||
$this->chatProvider = $chatProvider;
|
||||
$this->userProvider = $userProvider;
|
||||
$this->demoProvider = $demoProvider;
|
||||
}
|
||||
|
||||
public function saveDemo(ParsedDemo $demo, Header $header, StoredDemo $storedDemo, Upload $upload): int {
|
||||
/** @var int[] $userMap [$demoUserId => $dbUserId] */
|
||||
$userMap = [0 => 0];
|
||||
public function saveDemo(ParsedDemo $demo, Header $header, StoredDemo $storedDemo, Upload $upload): int {
|
||||
/** @var int[] $userMap [$demoUserId => $dbUserId] */
|
||||
$userMap = [0 => 0];
|
||||
|
||||
$demoId = $this->demoProvider->storeDemo(new Demo(
|
||||
0,
|
||||
$storedDemo->getUrl(),
|
||||
$upload->getName(),
|
||||
$header->getServer(),
|
||||
$header->getDuration(),
|
||||
$header->getNick(),
|
||||
$header->getMap(),
|
||||
new \DateTime(),
|
||||
$upload->getRed(),
|
||||
$upload->getBlue(),
|
||||
$demo->getRedScore(),
|
||||
$demo->getBlueScore(),
|
||||
count($demo->getPlayers()),
|
||||
$upload->getUploaderId(),
|
||||
$upload->getHash(),
|
||||
$storedDemo->getBackend(),
|
||||
$storedDemo->getPath()
|
||||
), $storedDemo->getBackend(), $storedDemo->getPath());
|
||||
$demoId = $this->demoProvider->storeDemo(new Demo(
|
||||
0,
|
||||
$storedDemo->getUrl(),
|
||||
$upload->getName(),
|
||||
$header->getServer(),
|
||||
$header->getDuration(),
|
||||
$header->getNick(),
|
||||
$header->getMap(),
|
||||
new \DateTime(),
|
||||
$upload->getRed(),
|
||||
$upload->getBlue(),
|
||||
$demo->getRedScore(),
|
||||
$demo->getBlueScore(),
|
||||
count($demo->getPlayers()),
|
||||
$upload->getUploaderId(),
|
||||
$upload->getHash(),
|
||||
$storedDemo->getBackend(),
|
||||
$storedDemo->getPath()
|
||||
), $storedDemo->getBackend(), $storedDemo->getPath());
|
||||
|
||||
foreach ($demo->getPlayers() as $player) {
|
||||
$userId = $this->userProvider->getUserId($player->getSteamId());
|
||||
$userMap[$player->getDemoUserId()] = $userId;
|
||||
foreach ($demo->getPlayers() as $player) {
|
||||
$userId = $this->userProvider->getUserId($player->getSteamId());
|
||||
$userMap[$player->getDemoUserId()] = $userId;
|
||||
|
||||
$this->playerProvider->store(new Player(
|
||||
0,
|
||||
$demoId,
|
||||
$player->getDemoUserId(),
|
||||
$userId,
|
||||
$player->getName(),
|
||||
$player->getTeam(),
|
||||
$player->getClass()
|
||||
));
|
||||
}
|
||||
$this->playerProvider->store(new Player(
|
||||
0,
|
||||
$demoId,
|
||||
$player->getDemoUserId(),
|
||||
$userId,
|
||||
$player->getName(),
|
||||
$player->getTeam(),
|
||||
$player->getClass()
|
||||
));
|
||||
}
|
||||
|
||||
foreach ($demo->getKills() as $kill) {
|
||||
$this->killProvider->store(new Kill(
|
||||
0,
|
||||
$demoId,
|
||||
$userMap[$kill->getAttackerDemoId()],
|
||||
$userMap[$kill->getAssisterDemoId()],
|
||||
$userMap[$kill->getVictimDemoId()],
|
||||
$kill->getWeapon()
|
||||
));
|
||||
}
|
||||
foreach ($demo->getKills() as $kill) {
|
||||
$this->killProvider->store(new Kill(
|
||||
0,
|
||||
$demoId,
|
||||
$userMap[$kill->getAttackerDemoId()],
|
||||
$userMap[$kill->getAssisterDemoId()],
|
||||
$userMap[$kill->getVictimDemoId()],
|
||||
$kill->getWeapon()
|
||||
));
|
||||
}
|
||||
|
||||
foreach ($demo->getChat() as $chat) {
|
||||
$this->chatProvider->storeChatMessage($demoId, $chat);
|
||||
}
|
||||
foreach ($demo->getChat() as $chat) {
|
||||
$this->chatProvider->storeChatMessage($demoId, $chat);
|
||||
}
|
||||
|
||||
return $demoId;
|
||||
}
|
||||
return $demoId;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,35 +3,35 @@
|
|||
use Demostf\API\Data\StoredDemo;
|
||||
|
||||
class DemoStore {
|
||||
/** @var string */
|
||||
private $root;
|
||||
/** @var string */
|
||||
private $webroot;
|
||||
/** @var string */
|
||||
private $root;
|
||||
/** @var string */
|
||||
private $webroot;
|
||||
|
||||
public function __construct(string $root, string $webroot) {
|
||||
$this->root = $root;
|
||||
$this->webroot = $webroot;
|
||||
}
|
||||
public function __construct(string $root, string $webroot) {
|
||||
$this->root = $root;
|
||||
$this->webroot = $webroot;
|
||||
}
|
||||
|
||||
public function store(string $sourcePath, string $name): StoredDemo {
|
||||
$target = $this->generatePath($name);
|
||||
if (!is_dir(dirname($target))) {
|
||||
mkdir(dirname($target), 0777, true);
|
||||
}
|
||||
rename($sourcePath, $target);
|
||||
chmod($target, 0755);
|
||||
return new StoredDemo($this->getUrl($name), 'static', $target);
|
||||
}
|
||||
public function store(string $sourcePath, string $name): StoredDemo {
|
||||
$target = $this->generatePath($name);
|
||||
if (!is_dir(dirname($target))) {
|
||||
mkdir(dirname($target), 0777, true);
|
||||
}
|
||||
rename($sourcePath, $target);
|
||||
chmod($target, 0755);
|
||||
return new StoredDemo($this->getUrl($name), 'static', $target);
|
||||
}
|
||||
|
||||
private function generatePath(string $name): string {
|
||||
return $this->root . $this->getPrefix($name) . $name;
|
||||
}
|
||||
private function generatePath(string $name): string {
|
||||
return $this->root . $this->getPrefix($name) . $name;
|
||||
}
|
||||
|
||||
private function getPrefix(string $name) {
|
||||
return '/' . substr($name, 0, 2) . '/' . substr($name, 2, 2) . '/';
|
||||
}
|
||||
private function getPrefix(string $name) {
|
||||
return '/' . substr($name, 0, 2) . '/' . substr($name, 2, 2) . '/';
|
||||
}
|
||||
|
||||
private function getUrl(string $name): string {
|
||||
return 'https://' . $this->webroot . $this->getPrefix($name) . $name;
|
||||
}
|
||||
private function getUrl(string $name): string {
|
||||
return 'https://' . $this->webroot . $this->getPrefix($name) . $name;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,144 +6,144 @@ namespace Demostf\API\Demo;
|
|||
* HL2 demo metadata
|
||||
*/
|
||||
class Header {
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $type;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $version;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $version;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $protocol;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $protocol;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $server;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $server;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $nick;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $nick;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $map;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $map;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $game;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $game;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
protected $duration;
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
protected $duration;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $ticks;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $ticks;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $frames;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $frames;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $sigon;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $sigon;
|
||||
|
||||
public function __construct(
|
||||
string $type,
|
||||
int $version,
|
||||
int $protocol,
|
||||
string $server,
|
||||
string $nick,
|
||||
string $map,
|
||||
string $game,
|
||||
float $duration,
|
||||
int $ticks,
|
||||
int $frames,
|
||||
int $sigon
|
||||
) {
|
||||
$this->type = $type;
|
||||
$this->version = $version;
|
||||
$this->protocol = $protocol;
|
||||
$this->server = $server;
|
||||
$this->nick = $nick;
|
||||
$this->map = $map;
|
||||
$this->game = $game;
|
||||
$this->duration = $duration;
|
||||
$this->ticks = $ticks;
|
||||
$this->frames = $frames;
|
||||
$this->sigon = $sigon;
|
||||
}
|
||||
public function __construct(
|
||||
string $type,
|
||||
int $version,
|
||||
int $protocol,
|
||||
string $server,
|
||||
string $nick,
|
||||
string $map,
|
||||
string $game,
|
||||
float $duration,
|
||||
int $ticks,
|
||||
int $frames,
|
||||
int $sigon
|
||||
) {
|
||||
$this->type = $type;
|
||||
$this->version = $version;
|
||||
$this->protocol = $protocol;
|
||||
$this->server = $server;
|
||||
$this->nick = $nick;
|
||||
$this->map = $map;
|
||||
$this->game = $game;
|
||||
$this->duration = $duration;
|
||||
$this->ticks = $ticks;
|
||||
$this->frames = $frames;
|
||||
$this->sigon = $sigon;
|
||||
}
|
||||
|
||||
public function getDuration(): float {
|
||||
return $this->duration;
|
||||
}
|
||||
public function getDuration(): float {
|
||||
return $this->duration;
|
||||
}
|
||||
|
||||
public function getFrames(): int {
|
||||
return $this->frames;
|
||||
}
|
||||
public function getFrames(): int {
|
||||
return $this->frames;
|
||||
}
|
||||
|
||||
public function getGame(): string {
|
||||
return $this->game;
|
||||
}
|
||||
public function getGame(): string {
|
||||
return $this->game;
|
||||
}
|
||||
|
||||
public function getMap(): string {
|
||||
return $this->map;
|
||||
}
|
||||
public function getMap(): string {
|
||||
return $this->map;
|
||||
}
|
||||
|
||||
public function getNick(): string {
|
||||
return $this->nick;
|
||||
}
|
||||
public function getNick(): string {
|
||||
return $this->nick;
|
||||
}
|
||||
|
||||
public function getProtocol(): int {
|
||||
return $this->protocol;
|
||||
}
|
||||
public function getProtocol(): int {
|
||||
return $this->protocol;
|
||||
}
|
||||
|
||||
public function getServer(): string {
|
||||
return $this->server;
|
||||
}
|
||||
public function getServer(): string {
|
||||
return $this->server;
|
||||
}
|
||||
|
||||
public function getSigon(): int {
|
||||
return $this->sigon;
|
||||
}
|
||||
public function getSigon(): int {
|
||||
return $this->sigon;
|
||||
}
|
||||
|
||||
public function getTicks(): int {
|
||||
return $this->ticks;
|
||||
}
|
||||
public function getTicks(): int {
|
||||
return $this->ticks;
|
||||
}
|
||||
|
||||
public function getType(): string {
|
||||
return $this->type;
|
||||
}
|
||||
public function getType(): string {
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function getVersion(): int {
|
||||
return $this->version;
|
||||
}
|
||||
public function getVersion(): int {
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
public static function fromArray(array $info) {
|
||||
return new Header(
|
||||
$info['type'],
|
||||
$info['version'],
|
||||
$info['protocol'],
|
||||
$info['server'],
|
||||
$info['nick'],
|
||||
$info['map'],
|
||||
$info['game'],
|
||||
$info['duration'],
|
||||
$info['ticks'],
|
||||
$info['frames'],
|
||||
$info['sigon']
|
||||
);
|
||||
}
|
||||
public static function fromArray(array $info) {
|
||||
return new Header(
|
||||
$info['type'],
|
||||
$info['version'],
|
||||
$info['protocol'],
|
||||
$info['server'],
|
||||
$info['nick'],
|
||||
$info['map'],
|
||||
$info['game'],
|
||||
$info['duration'],
|
||||
$info['ticks'],
|
||||
$info['frames'],
|
||||
$info['sigon']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,44 +3,46 @@
|
|||
namespace Demostf\API\Demo;
|
||||
|
||||
class HeaderParser {
|
||||
/**
|
||||
* @param string $head string containing the demo header binary data
|
||||
* @return Header
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function parseString(string $head): Header {
|
||||
$info = @unpack('A8type/Iversion/Iprotocol/A260server/A260nick/A260map/A260game/fduration/Vticks/Vframes/Vsigon',
|
||||
$head);
|
||||
if (!isset($info['type']) || $info['type'] !== 'HL2DEMO') {
|
||||
throw new \InvalidArgumentException('Not an HL2 demo');
|
||||
}
|
||||
return Header::fromArray($info);
|
||||
}
|
||||
/**
|
||||
* @param string $head string containing the demo header binary data
|
||||
* @return Header
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function parseString(string $head): Header {
|
||||
$info = @unpack(
|
||||
'A8type/Iversion/Iprotocol/A260server/A260nick/A260map/A260game/fduration/Vticks/Vframes/Vsigon',
|
||||
$head
|
||||
);
|
||||
if (!isset($info['type']) || $info['type'] !== 'HL2DEMO') {
|
||||
throw new \InvalidArgumentException('Not an HL2 demo');
|
||||
}
|
||||
return Header::fromArray($info);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse demo info from a stream
|
||||
*
|
||||
* @param resource $stream
|
||||
* @return Header
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function parseStream($stream): Header {
|
||||
$head = fread($stream, 2048);
|
||||
return $this->parseString($head);
|
||||
}
|
||||
/**
|
||||
* Parse demo info from a stream
|
||||
*
|
||||
* @param resource $stream
|
||||
* @return Header
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function parseStream($stream): Header {
|
||||
$head = fread($stream, 2048);
|
||||
return $this->parseString($head);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse demo info from a local file
|
||||
*
|
||||
* @param string $path
|
||||
* @return Header
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function parseHeader(string $path): Header {
|
||||
if (!is_readable($path)) {
|
||||
throw new \InvalidArgumentException('Unable to open demo: ' . $path);
|
||||
}
|
||||
$fh = fopen($path, 'rb');
|
||||
return $this->parseStream($fh);
|
||||
}
|
||||
/**
|
||||
* Parse demo info from a local file
|
||||
*
|
||||
* @param string $path
|
||||
* @return Header
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function parseHeader(string $path): Header {
|
||||
if (!is_readable($path)) {
|
||||
throw new \InvalidArgumentException('Unable to open demo: ' . $path);
|
||||
}
|
||||
$fh = fopen($path, 'rb');
|
||||
return $this->parseStream($fh);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,118 +13,118 @@ use Demostf\API\Data\Player;
|
|||
* Processes the raw demo.js output to something more suitable for our purpose
|
||||
*/
|
||||
class Parser {
|
||||
const CLASSES = [
|
||||
1 => 'scout',
|
||||
2 => 'sniper',
|
||||
3 => 'soldier',
|
||||
4 => 'demoman',
|
||||
5 => 'medic',
|
||||
6 => 'heavyweapons',
|
||||
7 => 'pyro',
|
||||
8 => 'spy',
|
||||
9 => 'engineer'
|
||||
];
|
||||
const CLASSES = [
|
||||
1 => 'scout',
|
||||
2 => 'sniper',
|
||||
3 => 'soldier',
|
||||
4 => 'demoman',
|
||||
5 => 'medic',
|
||||
6 => 'heavyweapons',
|
||||
7 => 'pyro',
|
||||
8 => 'spy',
|
||||
9 => 'engineer'
|
||||
];
|
||||
|
||||
/** @var RawParser */
|
||||
private $rawParser;
|
||||
/** @var RawParser */
|
||||
private $rawParser;
|
||||
|
||||
public function __construct(RawParser $rawParser) {
|
||||
$this->rawParser = $rawParser;
|
||||
}
|
||||
public function __construct(RawParser $rawParser) {
|
||||
$this->rawParser = $rawParser;
|
||||
}
|
||||
|
||||
public function analyse(string $path): ParsedDemo {
|
||||
$data = $this->rawParser->parse($path);
|
||||
if (!is_array($data)) {
|
||||
throw new \InvalidArgumentException('Error parsing demo');
|
||||
}
|
||||
return $this->handleData($data);
|
||||
}
|
||||
public function analyse(string $path): ParsedDemo {
|
||||
$data = $this->rawParser->parse($path);
|
||||
if (!is_array($data)) {
|
||||
throw new \InvalidArgumentException('Error parsing demo');
|
||||
}
|
||||
return $this->handleData($data);
|
||||
}
|
||||
|
||||
private function handleData(array $data): ParsedDemo {
|
||||
$intervalPerTick = $data['intervalPerTick'];
|
||||
$red = 0;
|
||||
$blue = 0;
|
||||
/** @var ChatMessage[] $chat */
|
||||
$chat = [];
|
||||
/** @var ParsedPlayer[] $players */
|
||||
$players = [];
|
||||
foreach ($data['rounds'] as $round) {
|
||||
if ($round['winner'] === 'red') {
|
||||
$red++;
|
||||
} else {
|
||||
$blue++;
|
||||
}
|
||||
}
|
||||
private function handleData(array $data): ParsedDemo {
|
||||
$intervalPerTick = $data['intervalPerTick'];
|
||||
$red = 0;
|
||||
$blue = 0;
|
||||
/** @var ChatMessage[] $chat */
|
||||
$chat = [];
|
||||
/** @var ParsedPlayer[] $players */
|
||||
$players = [];
|
||||
foreach ($data['rounds'] as $round) {
|
||||
if ($round['winner'] === 'red') {
|
||||
$red++;
|
||||
} else {
|
||||
$blue++;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($data['chat'] as $message) {
|
||||
if (isset($message['from'])) {
|
||||
$chat[] = new ChatMessage($message['from'], (int)floor(($message['tick'] - $data['startTick']) * $intervalPerTick), $message['text']);
|
||||
}
|
||||
}
|
||||
foreach ($data['chat'] as $message) {
|
||||
if (isset($message['from'])) {
|
||||
$chat[] = new ChatMessage($message['from'], (int)floor(($message['tick'] - $data['startTick']) * $intervalPerTick), $message['text']);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($data['users'] as $player) {
|
||||
$class = 0;
|
||||
$classSpawns = 0;
|
||||
foreach ($player['classes'] as $classId => $spawns) {
|
||||
if ($spawns > $classSpawns) {
|
||||
$classSpawns = $spawns;
|
||||
$class = $classId;
|
||||
}
|
||||
}
|
||||
if ($class && $player['steamId']) {//skip spectators
|
||||
$players[] = new ParsedPlayer(
|
||||
$player['name'],
|
||||
$player['userId'],
|
||||
$this->convertSteamIdToCommunityId($player['steamId']),
|
||||
$player['team'],
|
||||
$this->getClassName((int)$class)
|
||||
);
|
||||
}
|
||||
}
|
||||
foreach ($data['users'] as $player) {
|
||||
$class = 0;
|
||||
$classSpawns = 0;
|
||||
foreach ($player['classes'] as $classId => $spawns) {
|
||||
if ($spawns > $classSpawns) {
|
||||
$classSpawns = $spawns;
|
||||
$class = $classId;
|
||||
}
|
||||
}
|
||||
if ($class && $player['steamId']) {//skip spectators
|
||||
$players[] = new ParsedPlayer(
|
||||
$player['name'],
|
||||
$player['userId'],
|
||||
$this->convertSteamIdToCommunityId($player['steamId']),
|
||||
$player['team'],
|
||||
$this->getClassName((int)$class)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$kills = array_map(function (array $death) {
|
||||
return new ParsedKill($death['killer'] ?? 0, $death['assister'] ?? 0, $death['victim'] ?? 0, $death['weapon']);
|
||||
}, $data['deaths']);
|
||||
$kills = array_map(function (array $death) {
|
||||
return new ParsedKill($death['killer'] ?? 0, $death['assister'] ?? 0, $death['victim'] ?? 0, $death['weapon']);
|
||||
}, $data['deaths']);
|
||||
|
||||
return new ParsedDemo(
|
||||
$red,
|
||||
$blue,
|
||||
$chat,
|
||||
$players,
|
||||
$kills
|
||||
);
|
||||
}
|
||||
return new ParsedDemo(
|
||||
$red,
|
||||
$blue,
|
||||
$chat,
|
||||
$players,
|
||||
$kills
|
||||
);
|
||||
}
|
||||
|
||||
private function getClassName(int $classId): string {
|
||||
return self::CLASSES[$classId] ?? 'Unknown';
|
||||
}
|
||||
private function getClassName(int $classId): string {
|
||||
return self::CLASSES[$classId] ?? 'Unknown';
|
||||
}
|
||||
|
||||
/**
|
||||
* Credit to https://github.com/koraktor/steam-condenser-php
|
||||
*
|
||||
* Converts a SteamID as reported by game servers to a 64bit numeric
|
||||
* SteamID as used by the Steam Community
|
||||
*
|
||||
* @param string $steamId The SteamID string as used on servers, like
|
||||
* <var>STEAM_0:0:12345</var>
|
||||
* @return string The converted 64bit numeric SteamID
|
||||
* @throws \InvalidArgumentException if the SteamID doesn't have the correct
|
||||
* format
|
||||
*/
|
||||
public function convertSteamIdToCommunityId($steamId) {
|
||||
if ($steamId === 'STEAM_ID_LAN' || $steamId === 'BOT') {
|
||||
throw new \InvalidArgumentException("Cannot convert SteamID \"$steamId\" to a community ID.");
|
||||
}
|
||||
if (preg_match('/^STEAM_[0-1]:[0-1]:[0-9]+$/', $steamId)) {
|
||||
$steamParts = explode(':', substr($steamId, 8));
|
||||
$steamId = $steamParts[0] + $steamParts[1] * 2 + 1197960265728;
|
||||
return '7656' . $steamId;
|
||||
} else if (preg_match('/^\[U:[0-1]:[0-9]+\]$/', $steamId)) {
|
||||
$steamParts = explode(':', substr($steamId, 3, -1));
|
||||
$steamId = $steamParts[0] + $steamParts[1] + 1197960265727;
|
||||
return '7656' . $steamId;
|
||||
} else {
|
||||
throw new \InvalidArgumentException("SteamID \"$steamId\" doesn't have the correct format.");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Credit to https://github.com/koraktor/steam-condenser-php
|
||||
*
|
||||
* Converts a SteamID as reported by game servers to a 64bit numeric
|
||||
* SteamID as used by the Steam Community
|
||||
*
|
||||
* @param string $steamId The SteamID string as used on servers, like
|
||||
* <var>STEAM_0:0:12345</var>
|
||||
* @return string The converted 64bit numeric SteamID
|
||||
* @throws \InvalidArgumentException if the SteamID doesn't have the correct
|
||||
* format
|
||||
*/
|
||||
public function convertSteamIdToCommunityId($steamId) {
|
||||
if ($steamId === 'STEAM_ID_LAN' || $steamId === 'BOT') {
|
||||
throw new \InvalidArgumentException("Cannot convert SteamID \"$steamId\" to a community ID.");
|
||||
}
|
||||
if (preg_match('/^STEAM_[0-1]:[0-1]:[0-9]+$/', $steamId)) {
|
||||
$steamParts = explode(':', substr($steamId, 8));
|
||||
$steamId = $steamParts[0] + $steamParts[1] * 2 + 1197960265728;
|
||||
return '7656' . $steamId;
|
||||
} elseif (preg_match('/^\[U:[0-1]:[0-9]+\]$/', $steamId)) {
|
||||
$steamParts = explode(':', substr($steamId, 3, -1));
|
||||
$steamId = $steamParts[0] + $steamParts[1] + 1197960265727;
|
||||
return '7656' . $steamId;
|
||||
} else {
|
||||
throw new \InvalidArgumentException("SteamID \"$steamId\" doesn't have the correct format.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,30 +11,30 @@ use GuzzleHttp\Exception\GuzzleException;
|
|||
* Doesn't do any post-processing on the result
|
||||
*/
|
||||
class RawParser {
|
||||
/** @var string */
|
||||
private $parserUrl;
|
||||
/** @var string */
|
||||
private $parserUrl;
|
||||
|
||||
public function __construct(string $parserUrl) {
|
||||
$this->parserUrl = $parserUrl;
|
||||
}
|
||||
public function __construct(string $parserUrl) {
|
||||
$this->parserUrl = $parserUrl;
|
||||
}
|
||||
|
||||
public function parse(string $path): ?array {
|
||||
try {
|
||||
$client = new Client();
|
||||
$response = $client->post($this->parserUrl, [
|
||||
'body' => fopen($path, 'r')
|
||||
]);
|
||||
$result = json_decode($response->getBody()->getContents(), true);
|
||||
if (is_null($result)) {
|
||||
throw new \Exception('Failed to parse demo, unexpected result from parser');
|
||||
} else {
|
||||
return $result;
|
||||
}
|
||||
} catch (GuzzleException $e) {
|
||||
if (strpos($e->getMessage(), 'cURL error 52') !== false) {
|
||||
throw new \Exception('Failed to parse demo, can\'t reach demo parser');
|
||||
}
|
||||
throw new \Exception('Failed to parse demo, ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
public function parse(string $path): ?array {
|
||||
try {
|
||||
$client = new Client();
|
||||
$response = $client->post($this->parserUrl, [
|
||||
'body' => fopen($path, 'r')
|
||||
]);
|
||||
$result = json_decode($response->getBody()->getContents(), true);
|
||||
if (is_null($result)) {
|
||||
throw new \Exception('Failed to parse demo, unexpected result from parser');
|
||||
} else {
|
||||
return $result;
|
||||
}
|
||||
} catch (GuzzleException $e) {
|
||||
if (strpos($e->getMessage(), 'cURL error 52') !== false) {
|
||||
throw new \Exception('Failed to parse demo, can\'t reach demo parser');
|
||||
}
|
||||
throw new \Exception('Failed to parse demo, ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue