////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////

package pp.battleship.game.server;

import org.junit.Test;
import pp.battleship.message.client.MapMessage;
import pp.battleship.message.client.ShootMessage;
import pp.battleship.message.server.EffectMessage;
import pp.battleship.message.server.GameDetails;
import pp.battleship.message.server.StartBattleMessage;
import pp.battleship.model.Battleship;
import pp.battleship.model.Shot;

import java.util.List;
import java.util.Properties;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static pp.battleship.model.Battleship.Status.NORMAL;
import static pp.battleship.model.Rotation.DOWN;
import static pp.battleship.model.Rotation.RIGHT;

/**
 * Integration test cases for the server game logic in a larger game, called "Game 2", where Player 1 (with id 0) wins.
 * The test cases for the players are contained in {@linkplain pp.battleship.game.client.ClientGame2Player1Test}
 * and {@linkplain pp.battleship.game.client.ClientGame2Player2Test}.
 *
 * @see pp.battleship.game.client.ClientGame2Player1Test
 * @see pp.battleship.game.client.ClientGame2Player2Test
 */
public class ServerGame2Test extends AbstractServerGameTest {
    static {
        final Properties props = new Properties();
        props.setProperty("map.width", "10");
        props.setProperty("map.height", "10");
        props.setProperty("ship.nums", "4,3,2,1");
        CONFIG.readFrom(props);
    }

    @Test
    public void testRun() {
        EffectMessage effectMsg;
        GameDetails details;
        StartBattleMessage startShooting;

        serverLogic.addPlayer(0); // Player 1
        serverLogic.addPlayer(1); // Player 2
        assertEquals(0, messages.peek().id());
        details = (GameDetails) messages.poll().msg();
        assertEquals(10, details.getWidth());
        assertEquals(10, details.getHeight());
        assertEquals(4, details.getShipNums().size());
        assertEquals(Integer.valueOf(4), details.getShipNums().get(1));
        assertEquals(Integer.valueOf(3), details.getShipNums().get(2));
        assertEquals(Integer.valueOf(2), details.getShipNums().get(3));
        assertEquals(Integer.valueOf(1), details.getShipNums().get(4));
        assertEquals(1, messages.peek().id());
        details = (GameDetails) messages.poll().msg();
        assertEquals(10, details.getWidth());
        assertEquals(10, details.getHeight());
        assertEquals(4, details.getShipNums().size());
        assertEquals(Integer.valueOf(4), details.getShipNums().get(1));
        assertEquals(Integer.valueOf(3), details.getShipNums().get(2));
        assertEquals(Integer.valueOf(2), details.getShipNums().get(3));
        assertEquals(Integer.valueOf(1), details.getShipNums().get(4));
        serverLogic.received(new MapMessage(List.of(new Battleship(3, 2, 3, DOWN), new Battleship(2, 2, 6, DOWN), new Battleship(2, 4, 6, RIGHT), new Battleship(2, 4, 4, RIGHT), new Battleship(1, 7, 6, RIGHT), new Battleship(1, 7, 4, RIGHT), new Battleship(1, 4, 2, RIGHT), new Battleship(1, 6, 2, RIGHT), new Battleship(4, 2, 8, RIGHT), new Battleship(3, 7, 8, RIGHT))), 1);
        serverLogic.received(new MapMessage(List.of(new Battleship(4, 0, 5, DOWN), new Battleship(3, 0, 9, DOWN), new Battleship(3, 0, 0, RIGHT), new Battleship(2, 4, 0, RIGHT), new Battleship(2, 2, 9, RIGHT), new Battleship(2, 5, 9, RIGHT), new Battleship(1, 8, 9, RIGHT), new Battleship(1, 7, 0, RIGHT), new Battleship(1, 9, 0, RIGHT), new Battleship(1, 9, 7, RIGHT))), 0);
        assertEquals(0, messages.peek().id());
        startShooting = (StartBattleMessage) messages.poll().msg();
        assertTrue(startShooting.isMyTurn());
        assertEquals(1, messages.peek().id());
        startShooting = (StartBattleMessage) messages.poll().msg();
        assertFalse(startShooting.isMyTurn());
        serverLogic.received(new ShootMessage(p(5, 5)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(5, 5, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(5, 5, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(5, 5)), 1);
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(5, 5, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(5, 5, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(5, 6)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(5, 6, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(5, 6, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(6, 6)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(6, 6, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(6, 6, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(5, 6)), 1);
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(5, 6, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(5, 6, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(4, 6)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(4, 6, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 2, 4, 6, RIGHT, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(4, 6, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 2, 4, 6, RIGHT, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(4, 8)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(4, 8, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(4, 8, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(5, 8)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(5, 8, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(5, 8, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(6, 8)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(6, 8, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(6, 8, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(3, 7)), 1);
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(3, 7, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(3, 7, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(3, 8)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(3, 8, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(3, 8, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(2, 8)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(2, 8, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 4, 2, 8, RIGHT, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(2, 8, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 4, 2, 8, RIGHT, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(0, 8)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(0, 8, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(0, 8, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(5, 9)), 1);
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(5, 9, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(5, 9, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(6, 9)), 1);
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(6, 9, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 2, 5, 9, RIGHT, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(6, 9, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 2, 5, 9, RIGHT, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(7, 7)), 1);
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(7, 7, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(7, 7, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(0, 6)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(0, 6, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(0, 6, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(2, 5)), 1);
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(2, 5, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(2, 5, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(7, 8)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(7, 8, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(7, 8, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(8, 8)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(8, 8, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(8, 8, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(9, 8)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(9, 8, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 3, 7, 8, RIGHT, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(9, 8, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 3, 7, 8, RIGHT, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(2, 6)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(2, 6, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(2, 6, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(2, 5)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(2, 5, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 2, 2, 6, DOWN, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(2, 5, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 2, 2, 6, DOWN, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(3, 3)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(3, 3, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(3, 3, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(8, 9)), 1);
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(8, 9, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 1, 8, 9, RIGHT, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(8, 9, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 1, 8, 9, RIGHT, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(5, 3)), 1);
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(5, 3, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(5, 3, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(2, 3)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(2, 3, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(2, 3, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(2, 2)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(2, 2, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(2, 2, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(2, 1)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(2, 1, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 3, 2, 3, DOWN, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(2, 1, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 3, 2, 3, DOWN, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(4, 4)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(4, 4, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(4, 4, true), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(5, 4)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(5, 4, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 2, 4, 4, RIGHT, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(5, 4, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 2, 4, 4, RIGHT, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(7, 4)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(7, 4, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 1, 7, 4, RIGHT, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(7, 4, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 1, 7, 4, RIGHT, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(9, 4)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(9, 4, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(9, 4, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(8, 4)), 1);
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(8, 4, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(8, 4, false), effectMsg.getShot());
        assertNull(effectMsg.getDestroyedShip());
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(7, 6)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(7, 6, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 1, 7, 6, RIGHT, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(7, 6, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 1, 7, 6, RIGHT, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(4, 2)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(4, 2, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 1, 4, 2, RIGHT, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(4, 2, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 1, 4, 2, RIGHT, NORMAL);
        assertNull(effectMsg.getRemainingOpponentShips());
        serverLogic.received(new ShootMessage(p(6, 2)), 0);
        assertEquals(0, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertTrue(effectMsg.isOwnShot());
        assertEquals(new Shot(6, 2, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 1, 6, 2, RIGHT, NORMAL);
        assertEquals(0, effectMsg.getRemainingOpponentShips().size());
        assertEquals(1, messages.peek().id());
        effectMsg = (EffectMessage) messages.poll().msg();
        assertFalse(effectMsg.isOwnShot());
        assertEquals(new Shot(6, 2, true), effectMsg.getShot());
        checkShip(effectMsg.getDestroyedShip(), 1, 6, 2, RIGHT, NORMAL);
        assertEquals(8, effectMsg.getRemainingOpponentShips().size());
        checkShip(effectMsg.getRemainingOpponentShips().get(0), 4, 0, 5, DOWN, NORMAL);
        checkShip(effectMsg.getRemainingOpponentShips().get(1), 3, 0, 9, DOWN, NORMAL);
        checkShip(effectMsg.getRemainingOpponentShips().get(2), 3, 0, 0, RIGHT, NORMAL);
        checkShip(effectMsg.getRemainingOpponentShips().get(3), 2, 4, 0, RIGHT, NORMAL);
        checkShip(effectMsg.getRemainingOpponentShips().get(4), 2, 2, 9, RIGHT, NORMAL);
        checkShip(effectMsg.getRemainingOpponentShips().get(5), 1, 7, 0, RIGHT, NORMAL);
        checkShip(effectMsg.getRemainingOpponentShips().get(6), 1, 9, 0, RIGHT, NORMAL);
        checkShip(effectMsg.getRemainingOpponentShips().get(7), 1, 9, 7, RIGHT, NORMAL);
        // Player 1 wins

        assertEquals(0, messages.size());
    }
}
