Private
Public Access
1
0
Files
MineSeeker/src/Util/RpcManager.php

189 lines
5.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php declare(strict_types=1);
/**
* This file is part of the SplendidBear Websites' projects.
*
* Copyright (c) 2019 @ www.splendidbear.org
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Util;
use App\Entity\Grid;
use App\Entity\GridRow;
use App\Entity\PlayedGame;
use App\Interfaces\RpcManagerInterface;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use JsonException;
use Psr\Log\LoggerInterface;
use RuntimeException;
/**
* Class RpcManager
*
* @package App\Util
* @author Lang <https://www.splendidbear.org>
* @category Class
* @license https://www.gnu.org/licenses/lgpl-3.0.en.html GNU Lesser General Public License
* @link www.splendidbear.org
* @since 2026. 04. 09.
*/
class RpcManager implements RpcManagerInterface
{
private const ROWS = 16;
private const COLS = 16;
private const MINES = 51;
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly LoggerInterface $logger,
) {
}
public function getConnectInformation($params): string
{
$gameAssoc = is_array($params) ? $params[0] : $params;
$playedGame = $this->entityManager
->getRepository(PlayedGame::class)
->findOneByGameAssoc($gameAssoc);
if (null === $playedGame) {
try {
return base64_encode(json_encode([
'users' => null,
'revealedCells' => null,
], JSON_THROW_ON_ERROR));
} catch (JsonException $e) {
throw new RuntimeException($e->getMessage());
}
}
$users = $this->getUserCollection($playedGame);
$revealedCells = $this->aggregateRevealedCells($playedGame);
try {
return base64_encode(json_encode([
'users' => $users,
'revealedCells' => $revealedCells,
], JSON_THROW_ON_ERROR));
} catch (JsonException $e) {
throw new RuntimeException($e->getMessage());
}
}
public function saveGrid(string $gameAssoc): bool
{
$existingGame = $this->entityManager
->getRepository(PlayedGame::class)
->findOneByGameAssoc($gameAssoc);
if (null !== $existingGame) {
return true;
}
$grid2d = $this->generateGrid();
$playedGame = new PlayedGame();
$grid = new Grid();
try {
foreach ($grid2d as $row) {
$gridRow = new GridRow();
$gridRow->setGridCol($row);
$gridRow->setGrid($grid);
$this->entityManager->persist($gridRow);
}
$grid->setPlayedGame($playedGame);
$this->entityManager->persist($grid);
$playedGame->setGameAssoc($gameAssoc);
$playedGame->setGrid($grid);
$playedGame->setCreated(new DateTime());
$playedGame->setUpdated(new DateTime());
$this->entityManager->persist($playedGame);
$this->entityManager->flush();
} catch (Exception $e) {
$this->logger->error($e->getMessage());
}
return true;
}
/**
* Generate a random 16×16 grid with 51 mines and adjacent-mine numbers.
*/
private function generateGrid(): array
{
// Build flat set: 51 mines ('m') + remaining water ('w')
$set = array_merge(
array_fill(0, self::MINES, 'm'),
array_fill(0, self::ROWS * self::COLS - self::MINES, 'w'),
);
// Fisher-Yates shuffle
for ($i = count($set) - 1; $i > 0; $i--) {
$j = random_int(0, $i);
[$set[$i], $set[$j]] = [$set[$j], $set[$i]];
}
// Reshape to 2-D
$grid = [];
for ($r = 0; $r < self::ROWS; $r++) {
$grid[$r] = array_slice($set, $r * self::COLS, self::COLS);
}
// Replace 'w' with adjacent-mine count
$dirs = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]];
for ($r = 0; $r < self::ROWS; $r++) {
for ($c = 0; $c < self::COLS; $c++) {
if ('w' !== $grid[$r][$c]) {
continue;
}
$count = 0;
foreach ($dirs as [$dr, $dc]) {
if (isset($grid[$r + $dr][$c + $dc]) && 'm' === $grid[$r + $dr][$c + $dc]) {
$count++;
}
}
$grid[$r][$c] = $count;
}
}
return $grid;
}
/**
* Collect all cells revealed so far, enriched with the player colour from each Step.
*/
private function aggregateRevealedCells(PlayedGame $playedGame): array
{
$all = [];
foreach ($playedGame->getSteps() as $step) {
if (null === $step->getRevealedCells()) {
continue;
}
$player = $step->getPlayer();
foreach ($step->getRevealedCells() as $cell) {
$all[] = array_merge($cell, ['player' => $player]);
}
}
return $all;
}
private function getUserCollection(PlayedGame $playedGame): array
{
return [
'red' => null !== $playedGame->getRed() ? $playedGame->getRed()->getUsername() : '',
'blue' => null !== $playedGame->getBlue() ? $playedGame->getBlue()->getUsername() : '',
'redAnon' => null !== $playedGame->getRedAnon() ? $playedGame->getRedAnon()->getUserName() : '',
'blueAnon' => null !== $playedGame->getBlueAnon()? $playedGame->getBlueAnon()->getUserName(): '',
];
}
}