public function onMessage(WebSocketConnection $connection, $msg)
 {
     $message = \Blackjack\json_parse($msg);
     if (!isset($message['alias'])) {
         return;
     }
     $alias = $message['alias'];
     if ($alias === 'subscribe') {
         if ($this->isSubscribed($connection) || !isset($message['table_id'])) {
             $connection->close();
             return;
         }
         $tableId = $message['table_id'];
         /** @var WebSocketObservableTable $table */
         $table = $this->tableManager->getTableById($tableId);
         if ($table === null) {
             return;
         }
         $this->subscribe($connection, $table);
         return;
     }
     if ($alias === 'unsubscribe') {
         if (!$this->isSubscribed($connection)) {
             return;
         }
         $this->unsubscribe($connection);
         return;
     }
     if ($alias === 'query') {
         $connection->send(json_encode(['alias' => 'tables', 'data' => ['tables' => $this->tableManager->getTables()->map(function (Table $table) {
             return ['id' => $table->getId(), 'players' => $table->getSeats()->filter(function (TableSeat $seat) {
                 return $seat->getPlayer() !== null;
             })->map(function (TableSeat $seat) {
                 return ['player' => $seat->getPlayer()->getName()];
             })->elements()];
         })->elements()]]));
         return;
     }
 }
 private function handlePlayerDisconnection(Connection $connection)
 {
     $player = $connection->getPlayer();
     $seat = $player->getSeat();
     $playerConnection = $this->getPlayerConnection($player);
     $this->connections = $this->connections->filter(function ($c) use($playerConnection) {
         return $c !== $playerConnection;
     });
     $this->removePlayerFromSeat($seat, $assignBot = true);
     if (!$seat->getTable()->onlySeatedByBots() || count($this->tableManager->getTables()) === 1) {
         // Skip destroying table if this table is the last one standing
         // Or there's at least one computer bot connected via TCP
         return;
     }
     $this->destroyTable($seat->getTable());
 }