1
0
Fork 0
mirror of https://codeberg.org/demostf/api.git synced 2026-06-03 09:54:17 +02:00

store kills directly with players

This commit is contained in:
Robin Appelman 2021-05-24 14:34:43 +02:00
commit 6d01061c58
11 changed files with 83 additions and 84 deletions

View file

@ -14,7 +14,6 @@ use Demostf\API\Providers\ChatProvider;
use Demostf\API\Providers\DemoListProvider; use Demostf\API\Providers\DemoListProvider;
use Demostf\API\Providers\DemoProvider; use Demostf\API\Providers\DemoProvider;
use Demostf\API\Providers\InfoProvider; use Demostf\API\Providers\InfoProvider;
use Demostf\API\Providers\KillProvider;
use Demostf\API\Providers\PlayerProvider; use Demostf\API\Providers\PlayerProvider;
use Demostf\API\Providers\UploadProvider; use Demostf\API\Providers\UploadProvider;
use Demostf\API\Providers\UserProvider; use Demostf\API\Providers\UserProvider;
@ -82,10 +81,6 @@ class Container {
return new InfoProvider($this->connection); return new InfoProvider($this->connection);
} }
public function getKillProvider(): KillProvider {
return new KillProvider($this->connection);
}
public function getPlayerProvider(): PlayerProvider { public function getPlayerProvider(): PlayerProvider {
return new PlayerProvider($this->connection); return new PlayerProvider($this->connection);
} }
@ -104,7 +99,6 @@ class Container {
$this->getUserProvider(), $this->getUserProvider(),
$this->getDemoProvider(), $this->getDemoProvider(),
new DemoSaver( new DemoSaver(
$this->getKillProvider(),
$this->getPlayerProvider(), $this->getPlayerProvider(),
$this->getChatProvider(), $this->getChatProvider(),
$this->getUserProvider(), $this->getUserProvider(),

View file

@ -12,8 +12,22 @@ class Player {
private string $name; private string $name;
private string $team; private string $team;
private string $class; private string $class;
private int $kills;
private int $assists;
private int $deaths;
public function __construct(int $id, int $demoId, int $demoUserId, int $userId, string $name, string $team, string $class) { public function __construct(
int $id,
int $demoId,
int $demoUserId,
int $userId,
string $name,
string $team,
string $class,
int $kills,
int $assists,
int $deaths
) {
$this->id = $id; $this->id = $id;
$this->demoId = $demoId; $this->demoId = $demoId;
$this->demoUserId = $demoUserId; $this->demoUserId = $demoUserId;
@ -21,6 +35,9 @@ class Player {
$this->name = $name; $this->name = $name;
$this->team = $team; $this->team = $team;
$this->class = $class; $this->class = $class;
$this->kills = $kills;
$this->assists = $assists;
$this->deaths = $deaths;
} }
public function getId(): int { public function getId(): int {
@ -50,4 +67,16 @@ class Player {
public function getClass(): string { public function getClass(): string {
return $this->class; return $this->class;
} }
public function getKills(): int {
return $this->kills;
}
public function getAssists(): int {
return $this->assists;
}
public function getDeaths(): int {
return $this->deaths;
}
} }

View file

@ -5,20 +5,17 @@ declare(strict_types=1);
namespace Demostf\API\Demo; namespace Demostf\API\Demo;
use DateTime; use DateTime;
use Demostf\API\Data\Kill;
use Demostf\API\Data\ParsedDemo; use Demostf\API\Data\ParsedDemo;
use Demostf\API\Data\Player; use Demostf\API\Data\Player;
use Demostf\API\Data\StoredDemo; use Demostf\API\Data\StoredDemo;
use Demostf\API\Data\Upload; use Demostf\API\Data\Upload;
use Demostf\API\Providers\ChatProvider; use Demostf\API\Providers\ChatProvider;
use Demostf\API\Providers\DemoProvider; use Demostf\API\Providers\DemoProvider;
use Demostf\API\Providers\KillProvider;
use Demostf\API\Providers\PlayerProvider; use Demostf\API\Providers\PlayerProvider;
use Demostf\API\Providers\UserProvider; use Demostf\API\Providers\UserProvider;
use Doctrine\DBAL\Connection; use Doctrine\DBAL\Connection;
class DemoSaver { class DemoSaver {
private KillProvider $killProvider;
private PlayerProvider $playerProvider; private PlayerProvider $playerProvider;
private ChatProvider $chatProvider; private ChatProvider $chatProvider;
private UserProvider $userProvider; private UserProvider $userProvider;
@ -26,14 +23,12 @@ class DemoSaver {
private Connection $connection; private Connection $connection;
public function __construct( public function __construct(
KillProvider $killProvider,
PlayerProvider $playerProvider, PlayerProvider $playerProvider,
ChatProvider $chatProvider, ChatProvider $chatProvider,
UserProvider $userProvider, UserProvider $userProvider,
DemoProvider $demoProvider, DemoProvider $demoProvider,
Connection $connection Connection $connection
) { ) {
$this->killProvider = $killProvider;
$this->playerProvider = $playerProvider; $this->playerProvider = $playerProvider;
$this->chatProvider = $chatProvider; $this->chatProvider = $chatProvider;
$this->userProvider = $userProvider; $this->userProvider = $userProvider;
@ -42,9 +37,6 @@ class DemoSaver {
} }
public function saveDemo(ParsedDemo $demo, Header $header, StoredDemo $storedDemo, Upload $upload): int { public function saveDemo(ParsedDemo $demo, Header $header, StoredDemo $storedDemo, Upload $upload): int {
/** @var int[] $userMap [$demoUserId => $dbUserId] */
$userMap = [0 => 0];
$this->connection->beginTransaction(); $this->connection->beginTransaction();
$demoId = $this->demoProvider->storeDemo(new Demo( $demoId = $this->demoProvider->storeDemo(new Demo(
@ -67,9 +59,30 @@ class DemoSaver {
$storedDemo->getPath() $storedDemo->getPath()
), $storedDemo->getBackend(), $storedDemo->getPath()); ), $storedDemo->getBackend(), $storedDemo->getPath());
$kills = [];
$assists = [];
$deaths = [];
foreach ($demo->getPlayers() as $player) {
$kills[$player->getDemoUserId()] = 0;
$assists[$player->getDemoUserId()] = 0;
$deaths[$player->getDemoUserId()] = 0;
}
foreach ($demo->getKills() as $kill) {
if ($kill->getAttackerDemoId()) {
$kills[$kill->getAttackerDemoId()]++;
}
if ($kill->getAssisterDemoId()) {
$assists[$kill->getAssisterDemoId()]++;
}
if ($kill->getVictimDemoId()) {
$deaths[$kill->getVictimDemoId()]++;
}
}
foreach ($demo->getPlayers() as $player) { foreach ($demo->getPlayers() as $player) {
$userId = $this->userProvider->getUserId($player->getSteamId(), $player->getName()); $userId = $this->userProvider->getUserId($player->getSteamId(), $player->getName());
$userMap[$player->getDemoUserId()] = $userId;
$this->playerProvider->store(new Player( $this->playerProvider->store(new Player(
0, 0,
@ -78,17 +91,10 @@ class DemoSaver {
$userId, $userId,
$player->getName(), $player->getName(),
$player->getTeam(), $player->getTeam(),
$player->getClass() $player->getClass(),
)); $kills[$player->getDemoUserId()],
} $assists[$player->getDemoUserId()],
$deaths[$player->getDemoUserId()]
foreach ($demo->getKills() as $kill) {
$this->killProvider->store(new Kill(
0,
$demoId,
$userMap[$kill->getAttackerDemoId()] ?? 0,
$userMap[$kill->getAssisterDemoId()] ?? 0,
$userMap[$kill->getVictimDemoId()] ?? 0
)); ));
} }

View file

@ -33,11 +33,8 @@ class DemoProvider extends BaseProvider {
public function get(int $id, bool $fetchDetails = true): ?Demo { public function get(int $id, bool $fetchDetails = true): ?Demo {
// sql magic // sql magic
$sql = 'WITH demokills AS (SELECT attacker_id, assister_id, victim_id FROM kills WHERE demo_id = ?) $sql = '
SELECT players.id, user_id, players.name, team, class, users.steamid, users.avatar, SELECT players.id, user_id, players.name, team, class, users.steamid, users.avatar, players.kills, players.assists, players.deaths
(SELECT COUNT(*) FROM demokills WHERE attacker_id=players.user_id) AS kills,
(SELECT COUNT(*) FROM demokills WHERE assister_id=players.user_id) AS assists,
(SELECT COUNT(*) FROM demokills WHERE victim_id=players.user_id) AS deaths
FROM players FROM players
INNER JOIN users ON players.user_id = users.id INNER JOIN users ON players.user_id = users.id
WHERE demo_id = ?'; WHERE demo_id = ?';
@ -49,7 +46,7 @@ class DemoProvider extends BaseProvider {
if ($fetchDetails) { if ($fetchDetails) {
$uploader = $this->userProvider->getById($demo->getUploader()); $uploader = $this->userProvider->getById($demo->getUploader());
$playerQuery = $this->connection->executeQuery($sql, [$demo->getId(), $demo->getId()]); $playerQuery = $this->connection->executeQuery($sql, [$demo->getId()]);
$players = $playerQuery->fetchAll(PDO::FETCH_ASSOC); $players = $playerQuery->fetchAll(PDO::FETCH_ASSOC);
$demo->setUploaderUser($uploader); $demo->setUploaderUser($uploader);

View file

@ -1,23 +0,0 @@
<?php
declare(strict_types=1);
namespace Demostf\API\Providers;
use Demostf\API\Data\Kill;
class KillProvider extends BaseProvider {
public function store(Kill $kill): int {
$query = $this->getQueryBuilder();
$query->insert('kills')
->values([
'demo_id' => $query->createNamedParameter($kill->getDemoId()),
'attacker_id' => $query->createNamedParameter($kill->getAttackerId()),
'assister_id' => $query->createNamedParameter($kill->getAssisterId()),
'victim_id' => $query->createNamedParameter($kill->getVictimId()),
]);
$query->execute();
return (int) $this->connection->lastInsertId();
}
}

View file

@ -17,6 +17,9 @@ class PlayerProvider extends BaseProvider {
'name' => $query->createNamedParameter($player->getName()), 'name' => $query->createNamedParameter($player->getName()),
'team' => $query->createNamedParameter($player->getTeam()), 'team' => $query->createNamedParameter($player->getTeam()),
'class' => $query->createNamedParameter($player->getClass()), 'class' => $query->createNamedParameter($player->getClass()),
'kills' => $query->createNamedParameter($player->getKills()),
'assists' => $query->createNamedParameter($player->getAssists()),
'deaths' => $query->createNamedParameter($player->getDeaths()),
]); ]);
$query->execute(); $query->execute();

View file

@ -15,7 +15,6 @@ use Demostf\API\Demo\DemoSaver;
use Demostf\API\Demo\Header; use Demostf\API\Demo\Header;
use Demostf\API\Providers\ChatProvider; use Demostf\API\Providers\ChatProvider;
use Demostf\API\Providers\DemoProvider; use Demostf\API\Providers\DemoProvider;
use Demostf\API\Providers\KillProvider;
use Demostf\API\Providers\PlayerProvider; use Demostf\API\Providers\PlayerProvider;
use Demostf\API\Providers\UserProvider; use Demostf\API\Providers\UserProvider;
use Demostf\API\Test\TestCase; use Demostf\API\Test\TestCase;
@ -74,7 +73,6 @@ class DemoSaverTest extends TestCase {
); );
$saver = new DemoSaver( $saver = new DemoSaver(
new KillProvider($this->getDatabaseConnection()),
new PlayerProvider($this->getDatabaseConnection()), new PlayerProvider($this->getDatabaseConnection()),
$chatProvider, $chatProvider,
$userProvider, $userProvider,

View file

@ -138,7 +138,7 @@ class DemoListProviderTest extends TestCase {
} }
private function addPlayer($demoId, $userId) { private function addPlayer($demoId, $userId) {
$player = new Player(0, $demoId, 0, $userId, 'foo', 'red', 'scout'); $player = new Player(0, $demoId, 0, $userId, 'foo', 'red', 'scout', 1, 2, 3);
$this->playerProvider->store($player); $this->playerProvider->store($player);
} }

View file

@ -5,11 +5,9 @@ declare(strict_types=1);
namespace Demostf\API\Test\Providers; namespace Demostf\API\Test\Providers;
use Demostf\API\Data\DemoPlayer; use Demostf\API\Data\DemoPlayer;
use Demostf\API\Data\Kill;
use Demostf\API\Data\Player; use Demostf\API\Data\Player;
use Demostf\API\Demo\Demo; use Demostf\API\Demo\Demo;
use Demostf\API\Providers\DemoProvider; use Demostf\API\Providers\DemoProvider;
use Demostf\API\Providers\KillProvider;
use Demostf\API\Providers\PlayerProvider; use Demostf\API\Providers\PlayerProvider;
use Demostf\API\Providers\UserProvider; use Demostf\API\Providers\UserProvider;
use Demostf\API\Test\TestCase; use Demostf\API\Test\TestCase;
@ -24,16 +22,12 @@ class DemoProviderTest extends TestCase {
/** @var PlayerProvider */ /** @var PlayerProvider */
private $playerProvider; private $playerProvider;
/** @var KillProvider */
private $killProvider;
public function setUp(): void { public function setUp(): void {
parent::setUp(); parent::setUp();
$this->userProvider = new UserProvider($this->getDatabaseConnection(), $this->getRandomGenerator()); $this->userProvider = new UserProvider($this->getDatabaseConnection(), $this->getRandomGenerator());
$this->provider = new DemoProvider($this->getDatabaseConnection(), $this->userProvider); $this->provider = new DemoProvider($this->getDatabaseConnection(), $this->userProvider);
$this->playerProvider = new PlayerProvider($this->getDatabaseConnection()); $this->playerProvider = new PlayerProvider($this->getDatabaseConnection());
$this->killProvider = new KillProvider($this->getDatabaseConnection());
} }
public function testGetNonExisting() { public function testGetNonExisting() {
@ -124,14 +118,10 @@ class DemoProviderTest extends TestCase {
); );
$id = $this->provider->storeDemo($demo, 'dummy', 'path'); $id = $this->provider->storeDemo($demo, 'dummy', 'path');
$player1 = $this->addPlayer($id, 101, $user1->getId(), 'red', 'scout'); $player1 = $this->addPlayer($id, 101, $user1->getId(), 'red', 'scout', 2, 0, 1);
$player2 = $this->addPlayer($id, 102, $user2->getId(), 'red', 'soldier'); $player2 = $this->addPlayer($id, 102, $user2->getId(), 'red', 'soldier', 0, 1, 0);
$player3 = $this->addPlayer($id, 103, $user3->getId(), 'blue', 'engineer'); $player3 = $this->addPlayer($id, 103, $user3->getId(), 'blue', 'engineer', 0, 0, 2);
$player4 = $this->addPlayer($id, 104, $user4->getId(), 'blue', 'spy'); $player4 = $this->addPlayer($id, 104, $user4->getId(), 'blue', 'spy', 1, 0, 0);
$this->addKill($id, $user1->getId(), 0, $user3->getId());
$this->addKill($id, $user1->getId(), $user2->getId(), $user3->getId());
$this->addKill($id, $user4->getId(), 0, $user1->getId());
$retrieved = $this->provider->get($id, true); $retrieved = $this->provider->get($id, true);
$this->assertInstanceOf(Demo::class, $retrieved); $this->assertInstanceOf(Demo::class, $retrieved);
@ -149,18 +139,22 @@ class DemoProviderTest extends TestCase {
], $players); ], $players);
} }
private function addPlayer(int $demoId, int $demoUserId, int $userId, string $team, string $class): int { private function addPlayer(
$player = new Player(0, $demoId, $demoUserId, $userId, 'user_' . $userId, $team, $class); int $demoId,
int $demoUserId,
int $userId,
string $team,
string $class,
int $kills,
int $assist,
int $deaths
): int {
$player = new Player(0, $demoId, $demoUserId, $userId, 'user_' . $userId, $team, $class, $kills, $assist,
$deaths);
return $this->playerProvider->store($player); return $this->playerProvider->store($player);
} }
private function addKill(int $demoId, int $attackerId, int $assisterId, int $victimId): int {
$kill = new Kill(0, $demoId, $attackerId, $assisterId, $victimId);
return $this->killProvider->store($kill);
}
public function testSetDemoUrl() { public function testSetDemoUrl() {
$uploaderSteamId = $this->getSteamId('12345', 'test'); $uploaderSteamId = $this->getSteamId('12345', 'test');
$this->userProvider->store($uploaderSteamId, 'test'); $this->userProvider->store($uploaderSteamId, 'test');

View file

@ -16,7 +16,6 @@ use Demostf\API\Demo\RawParser;
use Demostf\API\Error\InvalidKeyException; use Demostf\API\Error\InvalidKeyException;
use Demostf\API\Providers\ChatProvider; use Demostf\API\Providers\ChatProvider;
use Demostf\API\Providers\DemoProvider; use Demostf\API\Providers\DemoProvider;
use Demostf\API\Providers\KillProvider;
use Demostf\API\Providers\PlayerProvider; use Demostf\API\Providers\PlayerProvider;
use Demostf\API\Providers\UploadProvider; use Demostf\API\Providers\UploadProvider;
use Demostf\API\Providers\UserProvider; use Demostf\API\Providers\UserProvider;
@ -76,7 +75,6 @@ class UploadProviderTest extends TestCase {
$this->userProvider = new UserProvider($this->getDatabaseConnection(), $this->getRandomGenerator()); $this->userProvider = new UserProvider($this->getDatabaseConnection(), $this->getRandomGenerator());
$this->demoProvider = new DemoProvider($this->getDatabaseConnection(), $this->userProvider); $this->demoProvider = new DemoProvider($this->getDatabaseConnection(), $this->userProvider);
$this->demoSaver = new DemoSaver( $this->demoSaver = new DemoSaver(
new KillProvider($this->getDatabaseConnection()),
new PlayerProvider($this->getDatabaseConnection()), new PlayerProvider($this->getDatabaseConnection()),
new ChatProvider($this->getDatabaseConnection()), new ChatProvider($this->getDatabaseConnection()),
$this->userProvider, $this->userProvider,

View file

@ -75,7 +75,10 @@ class UserProviderTest extends TestCase {
$user->getId(), $user->getId(),
$user->getName(), $user->getName(),
'red', 'red',
'scout' 'scout',
1,
1,
1
)); ));
$this->getDatabaseConnection()->query('REFRESH MATERIALIZED VIEW name_list'); $this->getDatabaseConnection()->query('REFRESH MATERIALIZED VIEW name_list');