Browse Source

implement player stats

main
ghost 11 months ago
parent
commit
cdc15d7e7c
  1. 2
      README.md
  2. 31
      migrations/Version20240107151414.php
  3. 119
      src/Controller/CrontabController.php
  4. 126
      src/Entity/Player.php
  5. 23
      src/Repository/PlayerRepository.php

2
README.md

@ -16,7 +16,7 @@ Web Monitor for Half-Life based on [HLServers](https://github.com/YGGverse/HLSer @@ -16,7 +16,7 @@ Web Monitor for Half-Life based on [HLServers](https://github.com/YGGverse/HLSer
* `chown -R www-data:www-data var`
* `cp .env .env.local`
* `crontab -e` > `* * * * * /usr/bin/curl --silent http://localhost/crontab/online &> /dev/null`
* `crontab -e` > `* * * * * /usr/bin/curl --silent http://localhost/crontab/index &> /dev/null`
## Update

31
migrations/Version20240107151414.php

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20240107151414 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE TABLE player (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, crc32server BIGINT NOT NULL, crc32name BIGINT NOT NULL, joined BIGINT NOT NULL, updated BIGINT NOT NULL, online BIGINT NOT NULL, frags BIGINT NOT NULL, name VARCHAR(255) NOT NULL)');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('DROP TABLE player');
}
}

119
src/Controller/CrontabController.php

@ -10,19 +10,20 @@ use Symfony\Component\HttpFoundation\Response; @@ -10,19 +10,20 @@ use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use App\Entity\Online;
use App\Entity\Player;
use Doctrine\ORM\EntityManagerInterface;
class CrontabController extends AbstractController
{
#[Route(
'/crontab/online',
name: 'crontab_online',
'/crontab/index',
name: 'crontab_index',
methods:
[
'GET'
]
)]
public function online(
public function index(
?Request $request,
EntityManagerInterface $entityManagerInterface
): Response
@ -62,14 +63,14 @@ class CrontabController extends AbstractController @@ -62,14 +63,14 @@ class CrontabController extends AbstractController
$total = $players + $bots;
// Generate CRC32 server ID
$crc32Server = crc32(
$crc32server = crc32(
$hlserver->host . ':' . $hlserver->port
);
// Get last online value
$online = $entityManagerInterface->getRepository(Online::class)->findOneBy(
[
'crc32server' => $crc32Server
'crc32server' => $crc32server
],
[
'id' => 'DESC' // same as online.time but faster
@ -82,16 +83,16 @@ class CrontabController extends AbstractController @@ -82,16 +83,16 @@ class CrontabController extends AbstractController
is_null($online)
||
$players !== $online->getPlayers()
||
$bots !== $online->getBots()
||
$total !== $online->getTotal()
// ||
// $bots !== $online->getBots()
// ||
// $total !== $online->getTotal()
)
{
$online = new Online();
$online->setCrc32server(
$crc32Server
$crc32server
);
$online->setTime(
@ -116,6 +117,104 @@ class CrontabController extends AbstractController @@ -116,6 +117,104 @@ class CrontabController extends AbstractController
$entityManagerInterface->flush();
}
// Update player stats
if ($players)
{
foreach ((array) $server->GetPlayers() as $session)
{
// Validate fields
if
(
!isset($session['Name']) || mb_strlen($session['Name']) > 255
||
!isset($session['TimeF']) || (int) $session['TimeF'] < 0
||
!isset($session['Frags']) || (int) $session['Frags'] < 0
)
{
continue;
}
// Skip bots
if ($session['TimeF'] == '59:59')
{
continue;
}
// Generate CRC32 server ID
$crc32name = crc32(
$session['Name']
);
$player = $entityManagerInterface->getRepository(Player::class)->findOneBy(
[
'crc32server' => $crc32server,
'crc32name' => $crc32name,
]
);
// Player exists
if ($player)
{
$player->setUpdated(
time()
);
$player->setOnline(
time()
);
if ((int) $session['Frags'] > $player->getFrags())
{
$player->setFrags(
(int) $session['Frags']
);
}
}
// Create new player
else
{
$player = new Player();
$player->setCrc32server(
$crc32server
);
$player->setCrc32name(
$crc32name
);
$player->setJoined(
time()
);
$player->setUpdated(
time()
);
$player->setOnline(
time()
);
$player->setName(
(string) $session['Name']
);
$player->setFrags(
(int) $session['Frags']
);
}
// Update DB
$entityManagerInterface->persist(
$player
);
$entityManagerInterface->flush();
}
}
}
}
}

126
src/Entity/Player.php

@ -0,0 +1,126 @@ @@ -0,0 +1,126 @@
<?php
namespace App\Entity;
use App\Repository\PlayerRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: PlayerRepository::class)]
class Player
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(type: Types::BIGINT)]
private ?string $crc32server = null;
#[ORM\Column(type: Types::BIGINT)]
private ?string $crc32name = null;
#[ORM\Column(type: Types::BIGINT)]
private ?string $joined = null;
#[ORM\Column(type: Types::BIGINT)]
private ?string $updated = null;
#[ORM\Column(type: Types::BIGINT)]
private ?string $online = null;
#[ORM\Column(type: Types::BIGINT)]
private ?string $frags = null;
#[ORM\Column(length: 255)]
private ?string $name = null;
public function getId(): ?int
{
return $this->id;
}
public function getCrc32server(): ?string
{
return $this->crc32server;
}
public function setCrc32server(string $crc32server): static
{
$this->crc32server = $crc32server;
return $this;
}
public function getCrc32name(): ?string
{
return $this->crc32name;
}
public function setCrc32name(string $crc32name): static
{
$this->crc32name = $crc32name;
return $this;
}
public function getJoined(): ?string
{
return $this->joined;
}
public function setJoined(string $joined): static
{
$this->joined = $joined;
return $this;
}
public function getUpdated(): ?string
{
return $this->updated;
}
public function setUpdated(string $updated): static
{
$this->updated = $updated;
return $this;
}
public function getOnline(): ?string
{
return $this->online;
}
public function setOnline(string $online): static
{
$this->online = $online;
return $this;
}
public function getFrags(): ?string
{
return $this->frags;
}
public function setFrags(string $frags): static
{
$this->frags = $frags;
return $this;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): static
{
$this->name = $name;
return $this;
}
}

23
src/Repository/PlayerRepository.php

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
<?php
namespace App\Repository;
use App\Entity\Player;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<Player>
*
* @method Player|null find($id, $lockMode = null, $lockVersion = null)
* @method Player|null findOneBy(array $criteria, array $orderBy = null)
* @method Player[] findAll()
* @method Player[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class PlayerRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Player::class);
}
}
Loading…
Cancel
Save