2016-10-18 15:58:53 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace Mine\SeekerBundle\Topic;
|
|
|
|
|
|
2016-11-23 22:32:25 +01:00
|
|
|
use Doctrine\DBAL\Driver\PDOException;
|
2016-10-25 11:19:50 +02:00
|
|
|
use Doctrine\ORM\EntityManager;
|
2016-10-19 13:27:55 +02:00
|
|
|
use Gos\Bundle\WebSocketBundle\Client\ClientManipulatorInterface;
|
2016-10-18 15:58:53 +02:00
|
|
|
use Gos\Bundle\WebSocketBundle\Topic\TopicInterface;
|
|
|
|
|
use Gos\Bundle\WebSocketBundle\Router\WampRequest;
|
2016-11-01 10:52:39 +01:00
|
|
|
use Mine\SeekerBundle\Entity\Gamer;
|
2016-11-01 12:38:46 +01:00
|
|
|
use Mine\SeekerBundle\Entity\Step;
|
2016-10-18 15:58:53 +02:00
|
|
|
use Ratchet\ConnectionInterface;
|
|
|
|
|
use Ratchet\Wamp\Topic;
|
2016-11-01 10:52:39 +01:00
|
|
|
use Symfony\Component\HttpFoundation\RequestStack;
|
2016-10-18 15:58:53 +02:00
|
|
|
|
2016-11-01 11:54:38 +01:00
|
|
|
class MineseekerTopic implements TopicInterface
|
2016-10-18 15:58:53 +02:00
|
|
|
{
|
2016-10-19 13:27:55 +02:00
|
|
|
/** @var ClientManipulatorInterface */
|
|
|
|
|
protected $clientManipulator;
|
|
|
|
|
|
2016-10-25 11:19:50 +02:00
|
|
|
/** @var EntityManager */
|
2016-11-01 10:52:39 +01:00
|
|
|
protected $em;
|
|
|
|
|
|
|
|
|
|
/** @var RequestStack */
|
|
|
|
|
protected $requestStack;
|
2016-10-25 11:19:50 +02:00
|
|
|
|
2016-10-19 13:27:55 +02:00
|
|
|
/**
|
2016-11-01 11:54:38 +01:00
|
|
|
* MineseekerTopic constructor.
|
2016-10-19 13:27:55 +02:00
|
|
|
*
|
|
|
|
|
* @param $clientManipulator ClientManipulatorInterface
|
2016-10-25 11:19:50 +02:00
|
|
|
* @param EntityManager $entityManager
|
2016-11-01 10:52:39 +01:00
|
|
|
* @param RequestStack $requestStack
|
2016-10-19 13:27:55 +02:00
|
|
|
*/
|
2016-11-01 10:52:39 +01:00
|
|
|
public function __construct(ClientManipulatorInterface $clientManipulator, EntityManager $entityManager, RequestStack $requestStack)
|
2016-10-19 13:27:55 +02:00
|
|
|
{
|
|
|
|
|
$this->clientManipulator = $clientManipulator;
|
2016-11-01 10:52:39 +01:00
|
|
|
$this->em = $entityManager;
|
|
|
|
|
$this->requestStack = $requestStack;
|
2016-10-19 13:27:55 +02:00
|
|
|
}
|
2016-10-18 15:58:53 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This will receive any Subscription requests for this topic.
|
|
|
|
|
*
|
|
|
|
|
* @param ConnectionInterface $connection
|
|
|
|
|
* @param Topic $topic
|
|
|
|
|
* @param WampRequest $request
|
2016-11-24 23:41:40 +01:00
|
|
|
* @return void
|
2016-10-18 15:58:53 +02:00
|
|
|
*/
|
|
|
|
|
public function onSubscribe(ConnectionInterface $connection, Topic $topic, WampRequest $request)
|
|
|
|
|
{
|
2016-10-19 13:27:55 +02:00
|
|
|
/** this will broadcast the message to ALL subscribers of this topic. */
|
|
|
|
|
$user = $this->clientManipulator->getClient($connection);
|
2016-10-25 11:19:50 +02:00
|
|
|
$userName = is_string($user) ? $user : $user->getUsername();
|
|
|
|
|
|
2016-10-31 18:07:37 +01:00
|
|
|
/** if more user wants to connect than 2 to one channel */
|
|
|
|
|
if ($topic->count() > 2) {
|
|
|
|
|
$topic->remove($connection);
|
|
|
|
|
} else {
|
2016-11-24 23:41:40 +01:00
|
|
|
$users = $this->controlUsers($topic, $userName, $user);
|
2016-11-01 10:52:39 +01:00
|
|
|
|
2016-10-31 18:07:37 +01:00
|
|
|
$topic->broadcast([
|
|
|
|
|
'userTopicId' => $connection->resourceId,
|
|
|
|
|
'channel' => $topic->getId(),
|
|
|
|
|
'user' => $userName,
|
2016-11-01 10:52:39 +01:00
|
|
|
'userCnt' => $topic->count(),
|
2017-01-22 15:21:45 +01:00
|
|
|
'users' => $users,
|
|
|
|
|
'steps' => $this->getSteps($topic),
|
2016-10-31 18:07:37 +01:00
|
|
|
]);
|
|
|
|
|
}
|
2016-10-18 15:58:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This will receive any UnSubscription requests for this topic.
|
|
|
|
|
*
|
|
|
|
|
* @param ConnectionInterface $connection
|
|
|
|
|
* @param Topic $topic
|
|
|
|
|
* @param WampRequest $request
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
public function onUnSubscribe(ConnectionInterface $connection, Topic $topic, WampRequest $request)
|
|
|
|
|
{
|
2016-10-19 13:27:55 +02:00
|
|
|
/** this will broadcast the message to ALL subscribers of this topic. */
|
2016-10-18 15:58:53 +02:00
|
|
|
$topic->broadcast(['msg' => $connection->resourceId . " has left " . $topic->getId()]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This will receive any Publish requests for this topic.
|
|
|
|
|
*
|
|
|
|
|
* @param ConnectionInterface $connection
|
|
|
|
|
* @param Topic $topic
|
|
|
|
|
* @param WampRequest $request
|
|
|
|
|
* @param $event
|
|
|
|
|
* @param array $exclude
|
|
|
|
|
* @param array $eligible
|
|
|
|
|
* @return mixed|void
|
|
|
|
|
* @internal param Topic $Topic
|
|
|
|
|
* @internal param array $eligibles
|
|
|
|
|
*/
|
|
|
|
|
public function onPublish(ConnectionInterface $connection, Topic $topic, WampRequest $request, $event, array $exclude, array $eligible)
|
|
|
|
|
{
|
2016-10-25 11:19:50 +02:00
|
|
|
$user = $this->clientManipulator->getClient($connection);
|
|
|
|
|
$userName = is_string($user) ? $user : $user->getUsername();
|
|
|
|
|
|
2016-11-01 12:38:46 +01:00
|
|
|
/** Save every step by user to db */
|
2016-11-20 17:44:29 +01:00
|
|
|
if (null === $event['resign']) {
|
|
|
|
|
$this->saveStepToDb($topic, $event);
|
|
|
|
|
} else {
|
|
|
|
|
$this->saveResignToDb($topic, $event['resign']);
|
|
|
|
|
}
|
2016-11-01 12:38:46 +01:00
|
|
|
|
2016-10-18 15:58:53 +02:00
|
|
|
$topic->broadcast([
|
2016-10-25 11:19:50 +02:00
|
|
|
'userTopicId' => $connection->resourceId,
|
|
|
|
|
'channel' => $topic->getId(),
|
|
|
|
|
'user' => $userName,
|
|
|
|
|
'userCnt' => $topic->count(),
|
|
|
|
|
'data' => $event
|
2016-10-18 15:58:53 +02:00
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Like RPC is will use to prefix the channel
|
2016-11-01 12:58:09 +01:00
|
|
|
*
|
2016-10-18 15:58:53 +02:00
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
public function getName()
|
|
|
|
|
{
|
2016-11-01 11:54:38 +01:00
|
|
|
return 'mineseeker.topic';
|
2016-10-18 15:58:53 +02:00
|
|
|
}
|
2016-11-01 10:52:39 +01:00
|
|
|
|
2016-11-20 17:44:29 +01:00
|
|
|
/**
|
|
|
|
|
* Save Resign event to database
|
2016-11-24 23:41:40 +01:00
|
|
|
*
|
|
|
|
|
* @param $topic
|
|
|
|
|
* @param $color
|
2016-11-20 17:44:29 +01:00
|
|
|
*/
|
|
|
|
|
private function saveResignToDb($topic, $color)
|
|
|
|
|
{
|
2016-11-23 22:32:25 +01:00
|
|
|
$this->reConnect();
|
2016-11-20 17:44:29 +01:00
|
|
|
$gameAssoc = explode('/', $topic->getId())[2];
|
|
|
|
|
|
|
|
|
|
$playedGame = $this->em
|
|
|
|
|
->getRepository('MineSeekerBundle:PlayedGame')
|
|
|
|
|
->findOneByGameAssoc($gameAssoc);
|
|
|
|
|
|
|
|
|
|
$playedGame->setResign($color);
|
|
|
|
|
$this->em->persist($playedGame);
|
|
|
|
|
$this->em->flush();
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-01 12:38:46 +01:00
|
|
|
/**
|
2016-11-01 12:58:09 +01:00
|
|
|
* Save steps and point information to database
|
|
|
|
|
*
|
2016-11-01 12:38:46 +01:00
|
|
|
* @param $topic
|
|
|
|
|
* @param $event
|
|
|
|
|
*/
|
|
|
|
|
private function saveStepToDb($topic, $event)
|
|
|
|
|
{
|
2016-11-23 22:32:25 +01:00
|
|
|
$this->reConnect();
|
2016-11-01 12:38:46 +01:00
|
|
|
$gameAssoc = explode('/', $topic->getId())[2];
|
|
|
|
|
|
|
|
|
|
$playedGame = $this->em
|
|
|
|
|
->getRepository('MineSeekerBundle:PlayedGame')
|
|
|
|
|
->findOneByGameAssoc($gameAssoc);
|
|
|
|
|
|
|
|
|
|
$step = new Step();
|
|
|
|
|
|
|
|
|
|
$step->setRow($event['coords'][0]);
|
|
|
|
|
$step->setCol($event['coords'][1]);
|
|
|
|
|
$step->setWBomb($event['bomb']);
|
|
|
|
|
$step->setPlayedGame($playedGame);
|
2017-01-03 13:10:43 +01:00
|
|
|
$step->setCreated(new \DateTime());
|
2016-11-01 12:38:46 +01:00
|
|
|
$this->em->persist($step);
|
2016-11-01 12:58:09 +01:00
|
|
|
|
|
|
|
|
$playedGame->setBluePoints($event['bluePoints']);
|
|
|
|
|
$playedGame->setRedPoints($event['redPoints']);
|
2016-11-20 17:44:29 +01:00
|
|
|
$playedGame->setBlueExplodedBomb($event['blueExplodedBomb'] ? true : null);
|
|
|
|
|
$playedGame->setRedExplodedBomb($event['redExplodedBomb'] ? true : null);
|
2017-01-03 13:10:43 +01:00
|
|
|
$playedGame->setUpdated(new \DateTime());
|
2016-11-01 12:58:09 +01:00
|
|
|
$this->em->persist($playedGame);
|
|
|
|
|
|
2016-11-01 12:38:46 +01:00
|
|
|
$this->em->flush();
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-22 15:21:45 +01:00
|
|
|
private function getSteps($topic)
|
|
|
|
|
{
|
|
|
|
|
$this->reConnect();
|
|
|
|
|
$gameAssoc = explode('/', $topic->getId())[2];
|
|
|
|
|
|
|
|
|
|
$playedGame = $this->em
|
|
|
|
|
->getRepository('MineSeekerBundle:PlayedGame')
|
|
|
|
|
->findOneByGameAssoc($gameAssoc);
|
|
|
|
|
|
|
|
|
|
$steps = array();
|
|
|
|
|
|
|
|
|
|
foreach ($playedGame->getStep()->toArray() as $item) {
|
|
|
|
|
$steps[] = array(
|
|
|
|
|
'row' => $item->getRow(),
|
|
|
|
|
'col' => $item->getCol(),
|
|
|
|
|
'wBomb' => $item->getWBomb(),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return base64_encode(json_encode($steps));
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-24 23:41:40 +01:00
|
|
|
/**
|
|
|
|
|
* Control all users in a channel
|
|
|
|
|
*
|
|
|
|
|
* @param $topic
|
|
|
|
|
* @param $userName
|
|
|
|
|
* @param $user
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
|
|
|
|
private function controlUsers($topic, $userName, $user)
|
|
|
|
|
{
|
2016-12-14 15:50:48 +01:00
|
|
|
$this->reConnect();
|
2016-11-24 23:41:40 +01:00
|
|
|
$gameAssoc = explode('/', $topic->getId())[2];
|
|
|
|
|
|
|
|
|
|
$playedGame = $this->em
|
|
|
|
|
->getRepository('MineSeekerBundle:PlayedGame')
|
|
|
|
|
->findOneByGameAssoc($gameAssoc);
|
|
|
|
|
|
2016-11-30 20:15:56 +01:00
|
|
|
/** @var $users {array} */
|
2016-11-24 23:41:40 +01:00
|
|
|
$users = $this->getUserCollection($playedGame);
|
|
|
|
|
|
2016-11-30 20:15:56 +01:00
|
|
|
$red = "" !== $users['red'] || "" !== $users['redAnon'] ? 1 : 0;
|
|
|
|
|
$blue = "" !== $users['blue'] || "" !== $users['blueAnon'] ? 1 : 0;
|
|
|
|
|
$one = $topic->count() === 1;
|
|
|
|
|
$two = $topic->count() === 2;
|
|
|
|
|
|
2016-11-24 23:41:40 +01:00
|
|
|
/** This checks it is a reconnection */
|
2016-11-30 20:15:56 +01:00
|
|
|
if (($one && ($red + $blue === 0)) || ($two && ($red + $blue === 1))) {
|
|
|
|
|
/** @var $users {array} w/ save users to database */
|
2017-01-24 23:00:51 +01:00
|
|
|
$users = $this->saveUserToDb($playedGame, $userName, $user, $topic->count());
|
2016-11-24 23:41:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $users;
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-01 12:38:46 +01:00
|
|
|
/**
|
2016-11-01 12:58:09 +01:00
|
|
|
* Save user data to database
|
|
|
|
|
*
|
2017-01-24 23:00:51 +01:00
|
|
|
* @param $playedGame
|
2016-11-01 12:38:46 +01:00
|
|
|
* @param $userName
|
|
|
|
|
* @param $user
|
|
|
|
|
* @param $count
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
2017-01-24 23:00:51 +01:00
|
|
|
private function saveUserToDb($playedGame, $userName, $user, $count)
|
2016-11-01 10:52:39 +01:00
|
|
|
{
|
2016-11-23 22:32:25 +01:00
|
|
|
$this->reConnect();
|
2016-11-01 10:52:39 +01:00
|
|
|
|
2016-11-30 20:15:56 +01:00
|
|
|
/** the user is not anonym */
|
2016-11-01 10:52:39 +01:00
|
|
|
if (!is_string($user)) {
|
|
|
|
|
$FOSUser = $this->em
|
|
|
|
|
->getRepository('JotunheimrUserBundle:User')
|
|
|
|
|
->findOneByUsername($userName);
|
|
|
|
|
|
2016-11-19 15:45:52 +01:00
|
|
|
if ($count == 1) {
|
|
|
|
|
/** @var $random {integer} Active player: red: 0, blue: 1 */
|
|
|
|
|
$random = rand(0, 1);
|
|
|
|
|
!$random ? $playedGame->setRed($FOSUser) : $playedGame->setBlue($FOSUser);
|
|
|
|
|
} else {
|
|
|
|
|
null === $playedGame->getRed() && null === $playedGame->getRedAnon()
|
|
|
|
|
? $playedGame->setRed($FOSUser)
|
|
|
|
|
: $playedGame->setBlue($FOSUser);
|
|
|
|
|
}
|
2016-11-01 10:52:39 +01:00
|
|
|
} else {
|
|
|
|
|
// $request = $this->requestStack->getCurrentRequest(); // TODO nem megy...
|
|
|
|
|
|
|
|
|
|
$anon = new Gamer();
|
|
|
|
|
$anon->setUserName($userName);
|
2016-11-30 20:15:56 +01:00
|
|
|
$anon->setConnTimestamp(new \DateTime());
|
2016-11-01 10:52:39 +01:00
|
|
|
$this->em->persist($anon);
|
|
|
|
|
|
2016-11-19 15:45:52 +01:00
|
|
|
if ($count == 1) {
|
|
|
|
|
/** @var $random {integer} Active player: red: 0, blue: 1 */
|
|
|
|
|
$random = rand(0, 1);
|
|
|
|
|
!$random ? $playedGame->setRedAnon($anon) : $playedGame->setBlueAnon($anon);
|
|
|
|
|
} else {
|
|
|
|
|
null === $playedGame->getRed() && null === $playedGame->getRedAnon()
|
|
|
|
|
? $playedGame->setRedAnon($anon)
|
|
|
|
|
: $playedGame->setBlueAnon($anon);
|
|
|
|
|
}
|
2016-11-01 10:52:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$this->em->persist($playedGame);
|
|
|
|
|
$this->em->flush();
|
|
|
|
|
|
2016-11-24 23:41:40 +01:00
|
|
|
return $this->getUserCollection($playedGame);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get user collection from PlayedGame entity
|
|
|
|
|
*
|
|
|
|
|
* @param $playedGame
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
|
|
|
|
private function getUserCollection($playedGame)
|
|
|
|
|
{
|
2016-11-01 10:52:39 +01:00
|
|
|
return array(
|
2016-11-01 13:20:14 +01:00
|
|
|
'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() : ''
|
2016-11-01 10:52:39 +01:00
|
|
|
);
|
|
|
|
|
}
|
2016-11-23 22:32:25 +01:00
|
|
|
|
2016-11-24 23:41:40 +01:00
|
|
|
/**
|
|
|
|
|
* Handle prod MySQL timeout
|
|
|
|
|
*/
|
2016-11-23 22:32:25 +01:00
|
|
|
private function reConnect()
|
|
|
|
|
{
|
|
|
|
|
try {
|
|
|
|
|
$connection = $this->em->getConnection();
|
|
|
|
|
|
|
|
|
|
if (false === $connection->ping()) {
|
|
|
|
|
$connection->close();
|
|
|
|
|
$connection->connect();
|
|
|
|
|
}
|
2017-01-22 15:21:45 +01:00
|
|
|
} catch (PDOException $ex) {
|
2016-11-23 22:32:25 +01:00
|
|
|
throw PDOException::class;
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-11-01 10:52:39 +01:00
|
|
|
}
|