/**
  * @param int[]    $flags
  * @param callable $closure
  */
 private function iterateCellFlags(array $flags, callable $closure)
 {
     foreach ($flags as $originFlag => $expectedFlag) {
         /** @var Cell $cell */
         $cell = $closure(MockFactory::getCellMock('A1')->setFlags($originFlag));
         $this->assertEquals($expectedFlag, $cell->getFlags());
     }
 }
 /**
  * @see TimestampedTrait::setTimestamp
  * @test
  */
 public function setTimestampSetOnPersist()
 {
     $result = MockFactory::getGameResultMock(2, 0);
     $player = $result->getGame()->getBattlefields()[0]->getPlayer();
     $result->setPlayer($player);
     static::$om->persist($result->getGame());
     $this->assertInstanceOf(\DateTime::class, $result->getTimestamp());
 }
 /**
  * @see BattlefieldModel::flagWaterAroundShip
  * @test
  */
 public function flagWaterAroundShipOnA1AlreadyDead()
 {
     $battlefield = MockFactory::getBattlefieldMock();
     $battlefield->getCellByCoordinate('A1')->setFlags(CellModel::FLAG_DEAD);
     $cell = $battlefield->getCellByCoordinate('B2')->setFlags(CellModel::FLAG_SHIP);
     BattlefieldModel::flagWaterAroundShip($cell);
     foreach (['A2', 'A3', 'B1', 'B3', 'C1', 'C2', 'C3'] as $coordinate) {
         $this->assertTrue($battlefield->getCellByCoordinate($coordinate)->hasFlag(CellModel::FLAG_SKIP));
     }
 }
 /**
  * @see AbstractFlaggedEntity::hasMask
  * @test
  */
 public function hasFlag()
 {
     $cell = MockFactory::getCellMock('A1');
     $cell->setFlags(CellModel::FLAG_DEAD_SHIP);
     $this->assertTrue($cell->hasFlag(CellModel::FLAG_DEAD_SHIP));
     $this->assertTrue($cell->hasFlag(CellModel::FLAG_DEAD));
     $this->assertTrue($cell->hasFlag(CellModel::FLAG_SHIP));
     $cell->removeFlag(CellModel::FLAG_DEAD);
     $this->assertFalse($cell->hasFlag(CellModel::FLAG_DEAD_SHIP));
     $this->assertFalse($cell->hasFlag(CellModel::FLAG_DEAD));
 }
 /**
  * @see GameInitiationResponse::addBattlefield()
  * @test
  */
 public function addBattlefield()
 {
     $game = MockFactory::getGameMock();
     $game->getBattlefields()[0]->setPlayer(MockFactory::getAIPlayerMock(''))->getCellByCoordinate('A1')->setFlags(CellModel::FLAG_SHIP);
     $request = new GameInitiationResponse($game->getBattlefields());
     foreach ($request->getBattlefields() as $battlefield) {
         foreach ($battlefield->getCells() as $cell) {
             if (PlayerModel::isAIControlled($battlefield->getPlayer())) {
                 $this->assertEquals(CellModel::FLAG_NONE, $cell->getFlags());
             }
         }
     }
 }
 /**
  * should:
  *      generate X battlefields of Y size
  *      assign AI controlled player to the generated battlefield
  *      initiate ship cells for the generated battlefield
  *      attach generated battlefield to the Game
  *
  * @see GameBuilder::attachAIBattlefields
  * @test
  */
 public function attachAIBattlefields()
 {
     $game = MockFactory::getGameMock(0, 0);
     $this->invokeMethod(static::$gameBuilder, 'attachAIBattlefields', [$game, 2, 7]);
     $this->assertCount(2, $game->getBattlefields());
     foreach ($game->getBattlefields() as $battlefield) {
         $this->assertCount(49, $battlefield->getCells());
         $this->assertTrue(PlayerModel::isAIControlled($battlefield->getPlayer()));
         $this->assertTrue(BattlefieldModel::hasUnfinishedShips($battlefield));
         foreach ($battlefield->getCells() as $coordinate => $cell) {
             /** all battlefields associated with AI players currently have hardcoded ship into B2 cell */
             $expectedFlag = 'B2' === $coordinate ? CellModel::FLAG_SHIP : CellModel::FLAG_NONE;
             $this->assertEquals($expectedFlag, $cell->getFlags());
         }
     }
 }
 /**
  * @see GameResultModel::prepareResponse
  * @test
  */
 public function prepareResponse()
 {
     $perPage = static::$container->getParameter('battleship_game.setting.limits.per_page.game_results');
     /** populated 2 full pages of Game Results + 1 result */
     for ($i = 0; $i < $perPage * 2 + 1; $i++) {
         $result = MockFactory::getGameResultMock(2, 0);
         $player = $result->getGame()->getBattlefields()[0]->getPlayer();
         $result->setPlayer($player);
         static::$om->persist($result->getGame());
     }
     static::$om->flush();
     /** should be 3 pages in total */
     for ($page = 1; $page < 3; $page++) {
         $response = static::$gameResultModel->buildResponse($page);
         $this->assertEquals($page, $response->getMeta()[GameResultsResponse::META_INDEX_CURRENT_PAGE]);
         $this->assertEquals(3, $response->getMeta()[GameResultsResponse::META_INDEX_TOTAL_PAGES]);
         $this->assertInternalType('array', $response->getResults());
         $this->assertContainsOnlyInstancesOf(GameResult::class, $response->getResults());
         $this->assertLessThanOrEqual($perPage, count($response->getResults()));
     }
 }
 public function AdjacentCellsProvider() : array
 {
     $battlefield = MockFactory::getBattlefieldMock();
     $battlefield->getCellByCoordinate('A2')->setFlags(CellModel::FLAG_DEAD);
     $battlefield->getCellByCoordinate('A1')->setFlags(CellModel::FLAG_DEAD_SHIP);
     return ['defaults' => ['B2', ['A1', 'A2', 'A3', 'B1', 'B3', 'C1', 'C2', 'C3'], MockFactory::getBattlefieldMock(), 1, CellModel::FLAG_NONE, CellModel::FLAG_NONE], 'defaults: 2 dept' => ['B2', ['A1', 'A2', 'A3', 'B1', 'B3', 'B4', 'C1', 'C2', 'C3', 'D2', 'D4'], MockFactory::getBattlefieldMock(), 2, CellModel::FLAG_NONE, CellModel::FLAG_NONE], 'defaults: $onlyFlag: CellModel::FLAG_DEAD' => ['B2', ['A1', 'A2'], $battlefield, 1, CellModel::FLAG_DEAD, CellModel::FLAG_NONE], 'defaults: $excludeFlag: CellModel::FLAG_DEAD' => ['B2', ['A3', 'B1', 'B3', 'C1', 'C2', 'C3'], $battlefield, 1, CellModel::FLAG_NONE, CellModel::FLAG_DEAD]];
 }
 /**
  * @see AIStrategyService::chooseCells
  * @test
  */
 public function chooseCellsOnNoDeadCellsInBattlefield()
 {
     $this->assertEmpty(static::$aiStrategyService->chooseCells(MockFactory::getBattlefieldMock()));
 }
 /**
  * @see AIService::attackCell
  *
  * @param int $cellFlag
  * @param int $expectedFlag
  *
  * @throws AIException
  */
 private function attackCell(int $cellFlag, int $expectedFlag)
 {
     $cell = $this->invokeMethod(static::$ai, 'attackCell', [MockFactory::getCellMock('A1', $cellFlag)]);
     $this->assertEquals($expectedFlag, $cell->getFlags());
 }
        });
        it('should return 48 cells from 7x7 battlefield 48 of them not flagged with CellModel::FLAG_DEAD', function () {
            $this->battlefield->getCellByCoordinate('A1')->addFlag(CellModel::FLAG_DEAD);
            $cells = BattlefieldModel::getLiveCells($this->battlefield);
            expect($cells)->toBeA('array')->toHaveLength(48);
            $this->iterateRecievedCells($cells);
        });
        it('should return empty array from 7x7 battlefield all of them flagged with CellModel::FLAG_DEAD', function () {
            /** @var Cell $cell */
            foreach ($this->battlefield->getCells() as $cell) {
                $cell->addFlag(CellModel::FLAG_DEAD);
            }
            $cells = BattlefieldModel::getLiveCells($this->battlefield);
            expect($cells)->toBeA('array')->toHaveLength(0);
        });
    });
    /**
     * @see BattlefieldModel::hasUnfinishedShips
     */
    describe('::hasUnfinishedShips - should return true if Battlefield contains cells flagged with CellModel::FLAG_SHIP and not flagged with CellModel::FLAG_DEAD', function () {
        it('should return false', function () {
            $battlefield = MockFactory::getBattlefieldMock();
            expect(BattlefieldModel::hasUnfinishedShips($battlefield))->toBe(false);
        });
        it('should return true', function () {
            $battlefield = MockFactory::getBattlefieldMock();
            $battlefield->getCellByCoordinate('A1')->addFlag(CellModel::FLAG_SHIP);
            expect(BattlefieldModel::hasUnfinishedShips($battlefield))->toBe(true);
        });
    });
});
 /**
  * invoke game processing method to Win Game
  *
  * @see     GameProcessor::processTurn
  * @test
  *
  * @depends processTurnToNotWin
  */
 public function processTurnToWin()
 {
     $game = MockFactory::getGameMock();
     /** to make sure CPU will never win from one turn. */
     $game->getBattlefields()[0]->getCellByCoordinate('A1')->addFlag(CellModel::FLAG_SHIP);
     $game->getBattlefields()[0]->getCellByCoordinate('A2')->addFlag(CellModel::FLAG_SHIP);
     $game->getBattlefields()[1]->setPlayer(MockFactory::getAIPlayerMock(''));
     $game->getBattlefields()[1]->getCellByCoordinate('A1')->addFlag(CellModel::FLAG_SHIP);
     $game = static::$gameProcessor->processTurn($game->getBattlefields()[1]->getCellByCoordinate('A1'));
     $this->assertNotNull($game->getResult());
     $this->assertInstanceOf(GameResult::class, $game->getResult());
 }
 /**
  * @see GameTurnResponse::setCells
  * @test
  */
 public function setGameResultOnConstruct()
 {
     $gameResult = MockFactory::getGameResultMock();
     $response = new GameTurnResponse($gameResult->getGame(), []);
     $this->assertSame($gameResult, $response->getResult());
 }
 private function verifyCellsByStrategy(array $expectedCoordinates, int $strategy)
 {
     $cells = static::$strategyProcessor->process(MockFactory::getBattlefieldMock()->getCellByCoordinate('B2'), $strategy);
     $this->assertCount(count($expectedCoordinates), $cells);
     $this->assertContainsOnlyInstancesOf(Cell::class, $cells);
     foreach ($cells as $cell) {
         $this->assertContains($cell->getCoordinate(), $expectedCoordinates);
     }
 }
 /**
  * should return true if player marked by @see PlayerModel::FLAG_AI_CONTROLLED flag
  *
  * @see PlayerModel::isAIControlled
  * @test
  */
 public function isAIControlledOnFlagAIControlled()
 {
     $this->assertTrue(PlayerModel::isAIControlled(MockFactory::getAIPlayerMock('')));
 }