diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000000..887879bb64c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,18 @@ +version: "3.9" +services: + db: + image: mysql:8.0.28 + platform: linux/amd64 # mac m1 + restart: always + ports: + - "13306:3306" + environment: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: chess + MYSQL_USER: user + MYSQL_PASSWORD: password + TZ: Asia/Seoul + volumes: + - ./db/mysql/data:/var/lib/mysql + - ./db/mysql/config:/etc/mysql/conf.d + - ./db/mysql/init:/docker-entrypoint-initdb.d diff --git a/src/main/java/chess/ChessApplication.java b/src/main/java/chess/ChessApplication.java new file mode 100644 index 00000000000..eec01c6cb21 --- /dev/null +++ b/src/main/java/chess/ChessApplication.java @@ -0,0 +1,14 @@ +package chess; + +import chess.config.ChessConfigure; +import chess.controller.ChessController; + +public class ChessApplication { + public static void main(String[] args) { + + final ChessConfigure chessConfigure = new ChessConfigure(); + + new ChessController(chessConfigure.boardQueryService(), + chessConfigure.boardCommandService()).run(); + } +} diff --git a/src/main/java/chess/application/ChessApplication.java b/src/main/java/chess/application/ChessApplication.java deleted file mode 100644 index fc8644f8459..00000000000 --- a/src/main/java/chess/application/ChessApplication.java +++ /dev/null @@ -1,9 +0,0 @@ -package chess.application; - -import chess.controller.ChessController; - -public class ChessApplication { - public static void main(String[] args) { - new ChessController().run(); - } -} diff --git a/src/main/java/chess/common/IndexCommand.java b/src/main/java/chess/common/IndexCommand.java new file mode 100644 index 00000000000..07377dbd785 --- /dev/null +++ b/src/main/java/chess/common/IndexCommand.java @@ -0,0 +1,22 @@ +package chess.common; + +public enum IndexCommand { + + START_COMMAND_INDEX(0), + SOURCE_POSITION(1), + TARGET_POSITION(2), + POSITION_COLUMN(0), + POSITION_ROW(1), + POSITION_INDEX(1), + PIECE_INDEX(0); + + private final int value; + + IndexCommand(final int value) { + this.value = value; + } + + public int value() { + return value; + } +} diff --git a/src/main/java/chess/config/ChessConfigure.java b/src/main/java/chess/config/ChessConfigure.java new file mode 100644 index 00000000000..a11cf81d517 --- /dev/null +++ b/src/main/java/chess/config/ChessConfigure.java @@ -0,0 +1,25 @@ +package chess.config; + +import chess.dao.BoardDao; +import chess.domain.board.service.BoardCommandService; +import chess.domain.board.service.BoardQueryService; +import chess.domain.board.service.mapper.BoardMapper; + +public class ChessConfigure { + + public BoardDao boardDao() { + return new BoardDao(); + } + + public BoardMapper boardMapper() { + return new BoardMapper(); + } + + public BoardQueryService boardQueryService() { + return new BoardQueryService(boardDao(), boardMapper()); + } + + public BoardCommandService boardCommandService() { + return new BoardCommandService(boardDao(), boardMapper()); + } +} diff --git a/src/main/java/chess/controller/ChessController.java b/src/main/java/chess/controller/ChessController.java index 816690012ab..23aeffd6390 100644 --- a/src/main/java/chess/controller/ChessController.java +++ b/src/main/java/chess/controller/ChessController.java @@ -1,8 +1,14 @@ package chess.controller; import chess.domain.board.Board; -import chess.domain.board.BoardFactory; +import chess.domain.board.Turn; +import chess.domain.board.factory.BoardFactory; import chess.domain.board.position.Position; +import chess.domain.board.score.BoardScore; +import chess.domain.board.score.Score; +import chess.domain.board.search.BoardSearch; +import chess.domain.board.service.BoardCommandService; +import chess.domain.board.service.BoardQueryService; import chess.domain.piece.Color; import chess.view.Command; import chess.view.InputView; @@ -10,17 +16,28 @@ import java.util.List; +import static chess.common.IndexCommand.POSITION_COLUMN; +import static chess.common.IndexCommand.POSITION_ROW; +import static chess.common.IndexCommand.SOURCE_POSITION; +import static chess.common.IndexCommand.START_COMMAND_INDEX; +import static chess.common.IndexCommand.TARGET_POSITION; + public class ChessController { - private static final int START_COMMAND_INDEX = 0; - private static final int SOURCE_POSITION = 1; - private static final int TARGET_POSITION = 2; - private static final int POSITION_COLUMN = 0; - private static final int POSITION_ROW = 1; + private final BoardQueryService boardQueryService; + private final BoardCommandService boardCommandService; + + public ChessController(final BoardQueryService boardQueryService, + final BoardCommandService boardCommandService) { + this.boardQueryService = boardQueryService; + this.boardCommandService = boardCommandService; + } public void run() { - final BoardFactory boardFactory = new BoardFactory(); - final Board board = new Board(boardFactory); + System.out.println("새로운 게임을 시작하려면 1, 게임을 불러오려면 2를 누르세요."); + + final String newGameCommand = InputView.readNewGameCommand(); + final Board board = loadChessBoard(newGameCommand); final String command = InputView.readStartCommand(); @@ -28,41 +45,106 @@ public void run() { return; } - final Color turn = Color.WHITE; - startGame(board, turn); + startGame(board); + } + + private Board loadChessBoard(final String newGameCommand) { + + if (Command.isNewGame(newGameCommand)) { + + final Board board = Board.makeNewGame(new BoardFactory()); + final Long savedId = boardCommandService.registerBoard(board); + + board.assignId(savedId); + + return board; + } + + if (Command.isExistedGame(newGameCommand)) { + System.out.println("현재 진행하고 있는 게임 번호들입니다."); + + final List boardIds = boardQueryService.searchAllBoards(); + + OutputView.printGameCandidates(boardIds); + + System.out.println("불러올 게임의 번호를 입력해주세요."); + + final long loadGameId = InputView.readLoadGameCommand(); + + return boardQueryService.searchBoard(loadGameId); + } + + throw new IllegalArgumentException("올바르지 않은 command 입니다."); } - private void startGame(final Board board, Color turn) { + private void startGame(final Board board) { while (true) { OutputView.printBoard(board.chessBoard()); - final List moveCommand = InputView.readMoveCommand(); - - final String startCommand = moveCommand.get(START_COMMAND_INDEX); + final List moveCommands = InputView.readMoveCommand(); + final String startCommand = moveCommands.get(START_COMMAND_INDEX.value()); if (Command.isEnd(startCommand)) { - break; + end(board); + return; } - turn = movePiece(board, turn, moveCommand, startCommand); + if (Command.isStatus(startCommand)) { + status(board); + return; + } + + final Turn beforeTurn = board.turn(); + + if (Command.isMove(startCommand)) { + move(board, moveCommands); + } + + final BoardSearch boardSearch = BoardSearch.countPiecePerClassTypeFrom(board.chessBoard()); + + if (boardSearch.isKingDead()) { + final BoardScore boardScore = BoardScore.flatByColumnFrom(board.chessBoard()); + OutputView.printWinner(beforeTurn.color(), boardScore.calculateBoardScoreBy(beforeTurn.color())); + return; + } } } - private Color movePiece(final Board board, Color turn, final List moveCommands, final String startCommand) { - if (Command.isMove(startCommand)) { - final Position fromPosition = convertPositionFrom(moveCommands.get(SOURCE_POSITION)); - final Position toPosition = convertPositionFrom(moveCommands.get(TARGET_POSITION)); + private void end(final Board board) { + boardCommandService.modifyBoard(board); + } + + private void status(final Board board) { + final BoardScore boardScore = BoardScore.flatByColumnFrom(board.chessBoard()); + + final Score blackScore = boardScore.calculateBoardScoreBy(Color.BLACK); + final Score whiteScore = boardScore.calculateBoardScoreBy(Color.WHITE); + + OutputView.printWinner(whoIsWinner(blackScore, whiteScore), whiteScore, blackScore); + boardCommandService.modifyBoard(board); + } - board.move(fromPosition, toPosition, turn); + private void move(final Board board, final List moveCommands) { + final Position fromPosition = convertPositionFrom(moveCommands.get(SOURCE_POSITION.value())); + final Position toPosition = convertPositionFrom(moveCommands.get(TARGET_POSITION.value())); + + board.move(fromPosition, toPosition); + } + + private Color whoIsWinner(final Score blackScore, final Score whiteScore) { + if (blackScore.isGreaterThan(whiteScore)) { + return Color.BLACK; + } - turn = turn.opposite(); + if (blackScore.equals(whiteScore)) { + return Color.NONE; } - return turn; + return Color.WHITE; } private Position convertPositionFrom(String moveCommand) { - return new Position(moveCommand.charAt(POSITION_COLUMN), moveCommand.charAt(POSITION_ROW)); + return new Position(moveCommand.charAt(POSITION_COLUMN.value()), moveCommand.charAt(POSITION_ROW.value())); } } diff --git a/src/main/java/chess/dao/BoardDao.java b/src/main/java/chess/dao/BoardDao.java new file mode 100644 index 00000000000..8faa7673395 --- /dev/null +++ b/src/main/java/chess/dao/BoardDao.java @@ -0,0 +1,149 @@ +package chess.dao; + +import chess.domain.board.service.dto.BoardModifyRequest; +import chess.domain.board.service.dto.BoardRegisterRequest; +import chess.domain.board.service.dto.BoardSearchResponse; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +public class BoardDao { + + public Long save(final BoardRegisterRequest boardRegisterRequest) { + + final String query = "INSERT INTO BOARD(POSITION, TURN) VALUES (?, ?)"; + + try (final Connection connection = MySqlManager.establishConnection(); + final PreparedStatement preparedStatement = connection.prepareStatement(query, + Statement.RETURN_GENERATED_KEYS)) { + + preparedStatement.setString(1, boardRegisterRequest.position()); + preparedStatement.setString(2, boardRegisterRequest.turn()); + preparedStatement.executeUpdate(); + + return generateKey(preparedStatement); + } catch (SQLException e) { + System.err.println("DB 저장 오류: " + e.getMessage()); + } + + throw new IllegalStateException("DB 저장 오류입니다."); + } + + private Long generateKey(final PreparedStatement preparedStatement) throws SQLException { + try (final ResultSet resultSet = preparedStatement.getGeneratedKeys()) { + if (resultSet.next()) { + return resultSet.getLong(1); + } + } + + throw new IllegalStateException("DB 저장 오류입니다."); + } + + public Optional findById(final Long id) { + final String query = "SELECT * FROM BOARD WHERE BOARD_ID = ?"; + + try (final Connection connection = MySqlManager.establishConnection(); + final PreparedStatement preparedStatement = connection.prepareStatement(query)) { + + preparedStatement.setLong(1, id); + final ResultSet resultSet = preparedStatement.executeQuery(); + + return mappingToDtoFrom(resultSet); + + } catch (SQLException e) { + System.err.println("DB 조회 오류: " + e.getMessage()); + } + + return Optional.empty(); + } + + private Optional mappingToDtoFrom(final ResultSet resultSet) { + try { + if (resultSet.next()) { + return Optional.of(new BoardSearchResponse( + resultSet.getLong("BOARD_ID"), + resultSet.getString("POSITION"), + resultSet.getString("TURN") + )); + } + } catch (SQLException e) { + System.err.println("DB 조회 오류: " + e.getMessage()); + } + + return Optional.empty(); + } + + public List findAll() { + final String query = "SELECT * FROM BOARD"; + + try (final Connection connection = MySqlManager.establishConnection(); + final PreparedStatement preparedStatement = connection.prepareStatement(query)) { + + final ResultSet resultSet = preparedStatement.executeQuery(); + + return mappingToBoardDtosFrom(resultSet); + } catch (SQLException e) { + System.err.println("DB 조회 오류: " + e.getMessage()); + } + + return Collections.emptyList(); + } + + private List mappingToBoardDtosFrom(final ResultSet resultSet) { + try { + List boardSearchResponses = new ArrayList<>(); + + while (resultSet.next()) { + final BoardSearchResponse boardSearchResponse = new BoardSearchResponse( + resultSet.getLong("BOARD_ID"), + resultSet.getString("POSITION"), + resultSet.getString("TURN") + ); + + boardSearchResponses.add(boardSearchResponse); + } + + return boardSearchResponses; + } catch (SQLException e) { + System.err.println("DB 조회 오류: " + e.getMessage()); + } + return null; + } + + public void modifyById(final BoardModifyRequest boardModifyRequest) { + final String query = "UPDATE BOARD SET POSITION = ?, TURN = ? WHERE BOARD_ID = ?"; + + try (final Connection connection = MySqlManager.establishConnection(); + final PreparedStatement preparedStatement = connection.prepareStatement(query);) { + + preparedStatement.setString(1, boardModifyRequest.position()); + preparedStatement.setString(2, boardModifyRequest.turn()); + preparedStatement.setLong(3, boardModifyRequest.id()); + preparedStatement.executeUpdate(); + + } catch (SQLException e) { + System.err.println("DB 수정 오류: " + e.getMessage()); + } + } + + public void deleteById(final Long boardId) { + final String query = "DELETE FROM BOARD WHERE BOARD_ID = ?"; + + try (final Connection connection = MySqlManager.establishConnection(); + final PreparedStatement preparedStatement = connection.prepareStatement(query);) { + + preparedStatement.setLong(1, boardId); + preparedStatement.executeUpdate(); + + } catch (SQLException e) { + System.err.println("DB 삭제 오류: " + e.getMessage()); + } + } +} diff --git a/src/main/java/chess/dao/MySqlManager.java b/src/main/java/chess/dao/MySqlManager.java new file mode 100644 index 00000000000..c80043c1fe9 --- /dev/null +++ b/src/main/java/chess/dao/MySqlManager.java @@ -0,0 +1,49 @@ +package chess.dao; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; + +public class MySqlManager { + + private static final String SERVER = "localhost:13306"; + private static final String DATABASE = "chess"; + private static final String OPTION = "?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true"; + private static final String USERNAME = "root"; + private static final String PASSWORD = "root"; + + public static Connection establishConnection() { + try { + return DriverManager.getConnection("jdbc:mysql://" + SERVER + "/" + DATABASE + OPTION, USERNAME, PASSWORD); + } catch (final SQLException e) { + System.err.println("DB 연결 오류:" + e.getMessage()); + return null; + } + } + + public static void initMySQL() { + try (final Connection connection = establishConnection(); + final Statement statement = connection.createStatement()) { + + final String initSql = new String(Files.readAllBytes(Paths.get("src/main/resources/sql/schema.sql"))); + + String[] queries = initSql.split(";"); + + for (String query : queries) { + if (query.trim().isEmpty()) { + continue; + } + statement.execute(query); + } + + } catch (SQLException e) { + System.err.println("DB 연결 오류:" + e.getMessage()); + } catch (IOException e) { + System.err.println("테이블 초기화 오류" + e.getMessage()); + } + } +} diff --git a/src/main/java/chess/domain/board/Board.java b/src/main/java/chess/domain/board/Board.java index da338036a9a..e203db9d25a 100644 --- a/src/main/java/chess/domain/board/Board.java +++ b/src/main/java/chess/domain/board/Board.java @@ -1,5 +1,6 @@ package chess.domain.board; +import chess.domain.board.factory.BoardFactory; import chess.domain.board.position.Path; import chess.domain.board.position.Position; import chess.domain.piece.Color; @@ -10,21 +11,40 @@ public class Board { private final Map chessBoard; + private Long id; + private Turn turn; - public Board(final BoardFactory boardFactory) { + private Board(final BoardFactory boardFactory) { this.chessBoard = boardFactory.createInitialBoard(); + this.turn = new Turn(Color.WHITE); } - public void move(Position from, Position to, final Color nextTurn) { + private Board(final Long id, final Map chessBoard, final Turn turn) { + this.id = id; + this.chessBoard = chessBoard; + this.turn = turn; + } + + public static Board bringBackPreviousGame(final Map board, final Turn turn, final Long id) { + return new Board(id, board, turn); + } + + public static Board makeNewGame(final BoardFactory boardFactory) { + return new Board(boardFactory); + } + + public void move(Position from, Position to) { final Piece currentMovePiece = findPieceFrom(from); validateMoveFromEmpty(currentMovePiece); - validateTurn(currentMovePiece, nextTurn); + validateTurn(currentMovePiece); final Path path = currentMovePiece.searchPathTo(from, to, findPieceFrom(to)); validateObstacle(path); movePiece(from, to); + + turn = turn.change(); } private Piece findPieceFrom(final Position position) { @@ -37,8 +57,8 @@ private void validateMoveFromEmpty(final Piece piece) { } } - private void validateTurn(final Piece currentTurnPiece, final Color nextTurn) { - if (currentTurnPiece.isDifferentColor(nextTurn)) { + private void validateTurn(final Piece currentTurnPiece) { + if (currentTurnPiece.isNotMyTurn(turn)) { throw new IllegalArgumentException("차례에 맞는 말을 선택해 주세요"); } } @@ -54,7 +74,19 @@ private void movePiece(final Position from, final Position to) { chessBoard.put(to, movingPiece); } + public void assignId(final Long id) { + this.id = id; + } + public Map chessBoard() { return Map.copyOf(chessBoard); } + + public Turn turn() { + return turn; + } + + public Long id() { + return id; + } } diff --git a/src/main/java/chess/domain/board/Turn.java b/src/main/java/chess/domain/board/Turn.java new file mode 100644 index 00000000000..9258ea587e2 --- /dev/null +++ b/src/main/java/chess/domain/board/Turn.java @@ -0,0 +1,39 @@ +package chess.domain.board; + +import chess.domain.piece.Color; + +import java.util.Objects; + +public class Turn { + + private final Color color; + + public Turn(final Color color) { + this.color = color; + } + + public Turn change() { + return new Turn(color.opposite()); + } + + public Color color() { + return color; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final Turn turn = (Turn) o; + return color == turn.color; + } + + @Override + public int hashCode() { + return Objects.hash(color); + } +} diff --git a/src/main/java/chess/domain/board/BlackPiecePositionConstant.java b/src/main/java/chess/domain/board/factory/BlackPiecePositionConstant.java similarity index 94% rename from src/main/java/chess/domain/board/BlackPiecePositionConstant.java rename to src/main/java/chess/domain/board/factory/BlackPiecePositionConstant.java index f480147df99..8e8b178abb0 100644 --- a/src/main/java/chess/domain/board/BlackPiecePositionConstant.java +++ b/src/main/java/chess/domain/board/factory/BlackPiecePositionConstant.java @@ -1,4 +1,4 @@ -package chess.domain.board; +package chess.domain.board.factory; public enum BlackPiecePositionConstant { diff --git a/src/main/java/chess/domain/board/BoardFactory.java b/src/main/java/chess/domain/board/factory/BoardFactory.java similarity index 95% rename from src/main/java/chess/domain/board/BoardFactory.java rename to src/main/java/chess/domain/board/factory/BoardFactory.java index 380e808549b..a9992eb3d61 100644 --- a/src/main/java/chess/domain/board/BoardFactory.java +++ b/src/main/java/chess/domain/board/factory/BoardFactory.java @@ -1,15 +1,15 @@ -package chess.domain.board; +package chess.domain.board.factory; import chess.domain.board.position.Column; import chess.domain.board.position.Position; -import chess.domain.piece.Bishop; import chess.domain.piece.Color; -import chess.domain.piece.King; -import chess.domain.piece.Knight; -import chess.domain.piece.Pawn; import chess.domain.piece.Piece; -import chess.domain.piece.Queen; -import chess.domain.piece.Rook; +import chess.domain.piece.jumper.King; +import chess.domain.piece.jumper.Knight; +import chess.domain.piece.pawn.Pawn; +import chess.domain.piece.slider.Bishop; +import chess.domain.piece.slider.Queen; +import chess.domain.piece.slider.Rook; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/chess/domain/board/WhitePiecePositionConstant.java b/src/main/java/chess/domain/board/factory/WhitePiecePositionConstant.java similarity index 94% rename from src/main/java/chess/domain/board/WhitePiecePositionConstant.java rename to src/main/java/chess/domain/board/factory/WhitePiecePositionConstant.java index 13478e64ef2..b0de5b34e4a 100644 --- a/src/main/java/chess/domain/board/WhitePiecePositionConstant.java +++ b/src/main/java/chess/domain/board/factory/WhitePiecePositionConstant.java @@ -1,4 +1,4 @@ -package chess.domain.board; +package chess.domain.board.factory; public enum WhitePiecePositionConstant { diff --git a/src/main/java/chess/domain/board/position/Column.java b/src/main/java/chess/domain/board/position/Column.java index d706054699f..d68b1efd31e 100644 --- a/src/main/java/chess/domain/board/position/Column.java +++ b/src/main/java/chess/domain/board/position/Column.java @@ -1,7 +1,9 @@ package chess.domain.board.position; import java.util.Arrays; +import java.util.List; import java.util.NoSuchElementException; +import java.util.stream.Collectors; public enum Column { @@ -39,6 +41,13 @@ public static Column from(char value) { .orElseThrow(() -> new NoSuchElementException("이동할 수 없는 column 방향입니다.")); } + public static List findPossibleColumnCandidates() { + return Arrays.stream(values()) + .filter(it -> it.name().length() == 1) + .map(it -> it.name().toLowerCase()) + .collect(Collectors.toList()); + } + public int differenceBetween(Column other) { return value - other.value; } diff --git a/src/main/java/chess/domain/board/position/PositionCache.java b/src/main/java/chess/domain/board/position/PositionCache.java new file mode 100644 index 00000000000..ea086b2650f --- /dev/null +++ b/src/main/java/chess/domain/board/position/PositionCache.java @@ -0,0 +1,24 @@ +package chess.domain.board.position; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class PositionCache { + + private static final Map CACHE = new HashMap<>(); + + static { + final List columns = Column.findPossibleColumnCandidates(); + final List rows = Row.findPossibleRowCandidates(); + + columns.stream() + .flatMap(column -> rows.stream() + .map(row -> column + row)) + .forEach(key -> CACHE.put(key, true)); + } + + public static boolean isNotCaching(final String positionCandidate) { + return !CACHE.containsKey(positionCandidate); + } +} diff --git a/src/main/java/chess/domain/board/position/Row.java b/src/main/java/chess/domain/board/position/Row.java index a825f86a64d..e8c2ec0d54d 100644 --- a/src/main/java/chess/domain/board/position/Row.java +++ b/src/main/java/chess/domain/board/position/Row.java @@ -1,7 +1,9 @@ package chess.domain.board.position; import java.util.Arrays; +import java.util.List; import java.util.NoSuchElementException; +import java.util.stream.Collectors; public enum Row { @@ -36,6 +38,12 @@ public static Row from(char value) { .orElseThrow(() -> new NoSuchElementException("이동할 수 없는 row 방향입니다.")); } + public static List findPossibleRowCandidates() { + return Arrays.stream(values()) + .map(it -> it.value) + .collect(Collectors.toList()); + } + public int differenceBetween(Row other) { return value - other.value; } diff --git a/src/main/java/chess/domain/board/score/BoardScore.java b/src/main/java/chess/domain/board/score/BoardScore.java new file mode 100644 index 00000000000..3b545465cbb --- /dev/null +++ b/src/main/java/chess/domain/board/score/BoardScore.java @@ -0,0 +1,46 @@ +package chess.domain.board.score; + +import chess.domain.board.position.Column; +import chess.domain.board.position.Position; +import chess.domain.piece.Color; +import chess.domain.piece.Piece; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class BoardScore { + + private final List columnPieces; + + private BoardScore(final List columnPieces) { + this.columnPieces = columnPieces; + } + + public static BoardScore flatByColumnFrom(Map chessBoard) { + + final Map> collect = mapToPiecesByColumnFrom(chessBoard); + + return new BoardScore(collect.entrySet() + .stream() + .map(it -> new ColumnPiece(it.getValue())) + .collect(Collectors.toList())); + } + + private static Map> mapToPiecesByColumnFrom(final Map chessBoard) { + return chessBoard.entrySet() + .stream() + .collect(Collectors.groupingBy( + it -> it.getKey().column(), + Collectors.mapping(Map.Entry::getValue, + Collectors.toList()) + )); + } + + public Score calculateBoardScoreBy(final Color color) { + + return columnPieces.stream() + .map(it -> it.calculatePiecesScore(color)) + .reduce(Score.ZERO, Score::plus); + } +} diff --git a/src/main/java/chess/domain/board/score/ColumnPiece.java b/src/main/java/chess/domain/board/score/ColumnPiece.java new file mode 100644 index 00000000000..bf44d9ed5d7 --- /dev/null +++ b/src/main/java/chess/domain/board/score/ColumnPiece.java @@ -0,0 +1,76 @@ +package chess.domain.board.score; + +import chess.domain.piece.Color; +import chess.domain.piece.Piece; +import chess.domain.piece.jumper.King; +import chess.domain.piece.jumper.Knight; +import chess.domain.piece.pawn.Pawn; +import chess.domain.piece.slider.Bishop; +import chess.domain.piece.slider.Queen; +import chess.domain.piece.slider.Rook; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static chess.domain.board.score.PieceScore.BISHOP; +import static chess.domain.board.score.PieceScore.KING; +import static chess.domain.board.score.PieceScore.KNIGHT; +import static chess.domain.board.score.PieceScore.LOOK; +import static chess.domain.board.score.PieceScore.PAWN; +import static chess.domain.board.score.PieceScore.QUEEN; + +public class ColumnPiece { + + private static final Map, Score> scoreMap = Map.of( + Rook.class, Score.from(LOOK.value()), + Bishop.class, Score.from(BISHOP.value()), + Knight.class, Score.from(KNIGHT.value()), + Pawn.class, Score.from(PAWN.value()), + Queen.class, Score.from(QUEEN.value()), + King.class, Score.from(KING.value()) + ); + private static final Class PAWN_CLASS_TYPE = Pawn.class; + private static final int COUNT_MAP_DEFAULT_VALUE = 0; + private static final int SINGLE_PAWN_COUNT = 1; + private static final int VALUE_PER_ELEMENT = 1; + + private final List pieces; + + public ColumnPiece(final List pieces) { + this.pieces = List.copyOf(pieces); + } + + public Score calculatePiecesScore(final Color color) { + + final Map, Integer> classTypeMap = countPerClassTypeBy(color); + + final Score score = calculateScore(classTypeMap); + + if (hasSinglePawn(classTypeMap)) { + return score.plus(scoreMap.get(PAWN_CLASS_TYPE)); + } + + return score; + } + + private Map, Integer> countPerClassTypeBy(final Color color) { + return pieces.stream() + .filter(it -> it.isSameColor(color)) + .collect(Collectors.groupingBy( + Piece::getClass, + Collectors.summingInt(value -> VALUE_PER_ELEMENT))); + } + + private Score calculateScore(final Map, Integer> countingPerClassType) { + return countingPerClassType.entrySet() + .stream() + .map(it -> scoreMap.get(it.getKey()) + .multiply(it.getValue())) + .reduce(Score.ZERO, Score::plus); + } + + private boolean hasSinglePawn(final Map, Integer> countingPerClassType) { + return countingPerClassType.getOrDefault(PAWN_CLASS_TYPE, COUNT_MAP_DEFAULT_VALUE) == SINGLE_PAWN_COUNT; + } +} diff --git a/src/main/java/chess/domain/board/score/PieceScore.java b/src/main/java/chess/domain/board/score/PieceScore.java new file mode 100644 index 00000000000..407971e3ce7 --- /dev/null +++ b/src/main/java/chess/domain/board/score/PieceScore.java @@ -0,0 +1,21 @@ +package chess.domain.board.score; + +public enum PieceScore { + + LOOK(5), + BISHOP(3), + KNIGHT(2.5), + PAWN(0.5), + QUEEN(9), + KING(0); + + private final double value; + + PieceScore(final double value) { + this.value = value; + } + + public double value() { + return value; + } +} diff --git a/src/main/java/chess/domain/board/score/Score.java b/src/main/java/chess/domain/board/score/Score.java new file mode 100644 index 00000000000..4884d794429 --- /dev/null +++ b/src/main/java/chess/domain/board/score/Score.java @@ -0,0 +1,52 @@ +package chess.domain.board.score; + +import java.math.BigDecimal; +import java.util.Objects; + +public class Score { + + public static final Score ZERO = new Score(BigDecimal.ZERO); + + private final BigDecimal value; + + private Score(final BigDecimal value) { + this.value = value; + } + + public static Score from(final double value) { + return new Score(BigDecimal.valueOf(value)); + } + + public Score plus(final Score score) { + return new Score(value.add(score.value)); + } + + public Score multiply(final int repeat) { + return new Score(value.multiply(BigDecimal.valueOf(repeat))); + } + + public BigDecimal value() { + return value; + } + + public boolean isGreaterThan(final Score other) { + return value.compareTo(other.value) > 0; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final Score score = (Score) o; + return score.value.compareTo(value) == 0; + } + + @Override + public int hashCode() { + return Objects.hash(value); + } +} diff --git a/src/main/java/chess/domain/board/search/BoardSearch.java b/src/main/java/chess/domain/board/search/BoardSearch.java new file mode 100644 index 00000000000..66a103acaba --- /dev/null +++ b/src/main/java/chess/domain/board/search/BoardSearch.java @@ -0,0 +1,36 @@ +package chess.domain.board.search; + +import chess.domain.board.position.Position; +import chess.domain.piece.Piece; +import chess.domain.piece.jumper.King; + +import java.util.Map; +import java.util.stream.Collectors; + +public class BoardSearch { + + private static final int ELEMENTS_UNIT_VALUE = 1; + private static final int UPPER_LIMIT_KING_DEAD = 1; + private static final Class KING_CLASS_TYPE = King.class; + + private final Map, Integer> boardSearchingMap; + + private BoardSearch(final Map, Integer> boardSearchingMap) { + this.boardSearchingMap = boardSearchingMap; + } + + public static BoardSearch countPiecePerClassTypeFrom(final Map chessBoard) { + + return new BoardSearch(chessBoard.entrySet() + .stream() + .collect(Collectors.groupingBy( + it -> it.getValue().getClass(), + Collectors.summingInt(value -> ELEMENTS_UNIT_VALUE) + )) + ); + } + + public boolean isKingDead() { + return boardSearchingMap.get(KING_CLASS_TYPE) <= UPPER_LIMIT_KING_DEAD; + } +} diff --git a/src/main/java/chess/domain/board/service/BoardCommandService.java b/src/main/java/chess/domain/board/service/BoardCommandService.java new file mode 100644 index 00000000000..8841e7783a6 --- /dev/null +++ b/src/main/java/chess/domain/board/service/BoardCommandService.java @@ -0,0 +1,41 @@ +package chess.domain.board.service; + +import chess.dao.BoardDao; +import chess.domain.board.Board; +import chess.domain.board.service.dto.BoardModifyRequest; +import chess.domain.board.service.dto.BoardRegisterRequest; +import chess.domain.board.service.mapper.BoardMapper; + +public class BoardCommandService { + + private final BoardDao boardDao; + private final BoardMapper boardMapper; + + public BoardCommandService(final BoardDao boardDao, final BoardMapper boardMapper) { + this.boardDao = boardDao; + this.boardMapper = boardMapper; + } + + public Long registerBoard(final Board board) { + + final BoardRegisterRequest boardRegisterRequest = boardMapper.mapToBoardRegisterRequestFrom(board); + + return boardDao.save(boardRegisterRequest); + } + + public void modifyBoard(final Board board) { + + final BoardRegisterRequest boardRegisterRequest = boardMapper.mapToBoardRegisterRequestFrom(board); + + final BoardModifyRequest boardModifyRequest = new BoardModifyRequest(board.id(), + boardRegisterRequest.position(), + boardRegisterRequest.turn() + ); + + boardDao.modifyById(boardModifyRequest); + } + + public void deleteBoard(final Long boardId) { + boardDao.deleteById(boardId); + } +} diff --git a/src/main/java/chess/domain/board/service/BoardQueryService.java b/src/main/java/chess/domain/board/service/BoardQueryService.java new file mode 100644 index 00000000000..b376c8db422 --- /dev/null +++ b/src/main/java/chess/domain/board/service/BoardQueryService.java @@ -0,0 +1,42 @@ +package chess.domain.board.service; + +import chess.dao.BoardDao; +import chess.domain.board.Board; +import chess.domain.board.service.dto.BoardSearchResponse; +import chess.domain.board.service.mapper.BoardMapper; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.stream.Collectors; + +public class BoardQueryService { + + private final BoardDao boardDao; + private final BoardMapper boardMapper; + + public BoardQueryService(final BoardDao boardDao, final BoardMapper boardMapper) { + this.boardDao = boardDao; + this.boardMapper = boardMapper; + } + + public Board searchBoard(final Long boardId) { + + final BoardSearchResponse boardSearchResponse = boardDao.findById(boardId) + .orElseThrow(NoSuchElementException::new); + + return boardMapper.mapToBoardSearchResponseFrom(boardSearchResponse.position(), + boardSearchResponse.turn(), + boardSearchResponse.id() + ); + } + + public List searchAllBoards() { + + final List boardSearchResponses = boardDao.findAll(); + + return boardSearchResponses.stream() + .map(BoardSearchResponse::id) + .collect(Collectors.toList()); + } + +} diff --git a/src/main/java/chess/domain/board/service/dto/BoardModifyRequest.java b/src/main/java/chess/domain/board/service/dto/BoardModifyRequest.java new file mode 100644 index 00000000000..211d05784e4 --- /dev/null +++ b/src/main/java/chess/domain/board/service/dto/BoardModifyRequest.java @@ -0,0 +1,26 @@ +package chess.domain.board.service.dto; + +public class BoardModifyRequest { + + private final Long id; + private final String position; + private final String turn; + + public BoardModifyRequest(final Long id, final String position, final String turn) { + this.id = id; + this.position = position; + this.turn = turn; + } + + public Long id() { + return id; + } + + public String position() { + return position; + } + + public String turn() { + return turn; + } +} diff --git a/src/main/java/chess/domain/board/service/dto/BoardRegisterRequest.java b/src/main/java/chess/domain/board/service/dto/BoardRegisterRequest.java new file mode 100644 index 00000000000..e19c0ed7481 --- /dev/null +++ b/src/main/java/chess/domain/board/service/dto/BoardRegisterRequest.java @@ -0,0 +1,20 @@ +package chess.domain.board.service.dto; + +public class BoardRegisterRequest { + + private final String position; + private final String turn; + + public BoardRegisterRequest(final String position, final String turn) { + this.position = position; + this.turn = turn; + } + + public String position() { + return position; + } + + public String turn() { + return turn; + } +} diff --git a/src/main/java/chess/domain/board/service/dto/BoardSearchResponse.java b/src/main/java/chess/domain/board/service/dto/BoardSearchResponse.java new file mode 100644 index 00000000000..843b8b5e67d --- /dev/null +++ b/src/main/java/chess/domain/board/service/dto/BoardSearchResponse.java @@ -0,0 +1,26 @@ +package chess.domain.board.service.dto; + +public class BoardSearchResponse { + + private final Long id; + private final String position; + private final String turn; + + public BoardSearchResponse(final Long id, final String position, final String turn) { + this.id = id; + this.position = position; + this.turn = turn; + } + + public Long id() { + return id; + } + + public String position() { + return position; + } + + public String turn() { + return turn; + } +} diff --git a/src/main/java/chess/domain/board/service/mapper/BoardMapper.java b/src/main/java/chess/domain/board/service/mapper/BoardMapper.java new file mode 100644 index 00000000000..92f6e36a96e --- /dev/null +++ b/src/main/java/chess/domain/board/service/mapper/BoardMapper.java @@ -0,0 +1,68 @@ +package chess.domain.board.service.mapper; + +import chess.domain.board.Board; +import chess.domain.board.Turn; +import chess.domain.board.position.Position; +import chess.domain.board.service.dto.BoardRegisterRequest; +import chess.domain.piece.Color; +import chess.domain.piece.Piece; + +import java.util.Arrays; +import java.util.Map; +import java.util.stream.Collectors; + +import static chess.common.IndexCommand.PIECE_INDEX; +import static chess.common.IndexCommand.POSITION_COLUMN; +import static chess.common.IndexCommand.POSITION_INDEX; +import static chess.common.IndexCommand.POSITION_ROW; + +public class BoardMapper { + + private static final String POSITION_AND_PIECE_DELIM = ":"; + private static final String PIECE_DELIM = ","; + private static final String POSITION_DELIM = " "; + + public BoardRegisterRequest mapToBoardRegisterRequestFrom(final Board board) { + + final Map chessBoard = board.chessBoard(); + + final String chessPosition = chessBoard.entrySet() + .stream() + .map(entry -> { + final Position position = entry.getKey(); + return PieceInitialMapping.mapToPieceInitialFrom(entry.getValue()) + + POSITION_AND_PIECE_DELIM + + position.column().value() + + POSITION_DELIM + + position.row().value(); + }) + .collect(Collectors.joining(PIECE_DELIM)); + + return new BoardRegisterRequest(chessPosition, board.turn().color().name()); + } + + public Board mapToBoardSearchResponseFrom(final String position, + final String turn, final Long id) { + + final Map chessBoard = + Arrays.stream(position.split(PIECE_DELIM)) + .map(s -> s.split(POSITION_AND_PIECE_DELIM)) + .collect(Collectors.toMap( + arr -> { + final String[] s = arr[POSITION_INDEX.value()].trim() + .split(POSITION_DELIM); + + return new Position( + Integer.parseInt(s[POSITION_COLUMN.value()]), + Integer.parseInt(s[POSITION_ROW.value()]) + ); + }, + arr -> PieceInitialMapping.mapToPieceFrom( + arr[PIECE_INDEX.value()].trim()) + )); + + + return Board.bringBackPreviousGame(chessBoard, new Turn(Color.valueOf(turn)), id); + } + +} diff --git a/src/main/java/chess/domain/board/service/mapper/PieceInitialMapping.java b/src/main/java/chess/domain/board/service/mapper/PieceInitialMapping.java new file mode 100644 index 00000000000..1b7c255c8be --- /dev/null +++ b/src/main/java/chess/domain/board/service/mapper/PieceInitialMapping.java @@ -0,0 +1,63 @@ +package chess.domain.board.service.mapper; + +import chess.domain.piece.Color; +import chess.domain.piece.Piece; +import chess.domain.piece.jumper.King; +import chess.domain.piece.jumper.Knight; +import chess.domain.piece.pawn.Pawn; +import chess.domain.piece.slider.Bishop; +import chess.domain.piece.slider.Queen; +import chess.domain.piece.slider.Rook; + +import java.util.Arrays; +import java.util.NoSuchElementException; + +public enum PieceInitialMapping { + + K(Color.BLACK, King.class, new King(Color.BLACK)), + k(Color.WHITE, King.class, new King(Color.WHITE)), + Q(Color.BLACK, Queen.class, new Queen(Color.BLACK)), + q(Color.WHITE, Queen.class, new Queen(Color.WHITE)), + R(Color.BLACK, Rook.class, new Rook(Color.BLACK)), + r(Color.WHITE, Rook.class, new Rook(Color.WHITE)), + N(Color.BLACK, Knight.class, new Knight(Color.BLACK)), + n(Color.WHITE, Knight.class, new Knight(Color.WHITE)), + B(Color.BLACK, Bishop.class, new Bishop(Color.BLACK)), + b(Color.WHITE, Bishop.class, new Bishop(Color.WHITE)), + P(Color.BLACK, Pawn.class, new Pawn(Color.BLACK)), + p(Color.WHITE, Pawn.class, new Pawn(Color.WHITE)); + + private final Color color; + private final Class classType; + private final Piece piece; + + PieceInitialMapping(final Color color, final Class classType, final Piece piece) { + this.color = color; + this.classType = classType; + this.piece = piece; + } + + public static String mapToPieceInitialFrom(final Piece piece) { + return Arrays.stream(values()) + .filter(it -> piece.isSameColor(it.color) && it.classType.equals(piece.getClass())) + .map(it -> it.name()) + .findFirst() + .orElseThrow(NoSuchElementException::new); + } + + public static Class mapToClassTypeFrom(final String pieceInitial) { + return Arrays.stream(values()) + .filter(it -> it.name().equals(pieceInitial)) + .map(it -> it.classType) + .findFirst() + .orElseThrow(NoSuchElementException::new); + } + + public static Piece mapToPieceFrom(final String pieceInitial) { + return Arrays.stream(values()) + .filter(it -> it.name().equals(pieceInitial)) + .map(it -> it.piece) + .findFirst() + .orElseThrow(NoSuchElementException::new); + } +} diff --git a/src/main/java/chess/domain/piece/Color.java b/src/main/java/chess/domain/piece/Color.java index 75340406bc1..e307b7af612 100644 --- a/src/main/java/chess/domain/piece/Color.java +++ b/src/main/java/chess/domain/piece/Color.java @@ -3,7 +3,8 @@ public enum Color { BLACK, - WHITE; + WHITE, + NONE; public boolean isWhite() { return this == WHITE; @@ -21,6 +22,10 @@ public boolean isSameColor(Color color) { return this == color; } + public boolean isNone() { + return this == NONE; + } + public Color opposite() { if (this == BLACK) { return WHITE; diff --git a/src/main/java/chess/domain/piece/Piece.java b/src/main/java/chess/domain/piece/Piece.java index d31f831c16c..03aa72650ae 100644 --- a/src/main/java/chess/domain/piece/Piece.java +++ b/src/main/java/chess/domain/piece/Piece.java @@ -1,5 +1,6 @@ package chess.domain.piece; +import chess.domain.board.Turn; import chess.domain.board.position.Movement; import chess.domain.board.position.Path; import chess.domain.board.position.Position; @@ -49,4 +50,12 @@ public boolean isDifferentColor(Color color) { public boolean isDifferentColor(Piece other) { return color.isDifferentColor(other.color); } + + public boolean isSameColor(Color color) { + return this.color.isSameColor(color); + } + + public boolean isNotMyTurn(final Turn turn) { + return this.color.isDifferentColor(turn.color()); + } } diff --git a/src/main/java/chess/domain/piece/JumperPiece.java b/src/main/java/chess/domain/piece/jumper/JumperPiece.java similarity index 95% rename from src/main/java/chess/domain/piece/JumperPiece.java rename to src/main/java/chess/domain/piece/jumper/JumperPiece.java index f755b79462d..9aa3a5f45e8 100644 --- a/src/main/java/chess/domain/piece/JumperPiece.java +++ b/src/main/java/chess/domain/piece/jumper/JumperPiece.java @@ -1,8 +1,10 @@ -package chess.domain.piece; +package chess.domain.piece.jumper; import chess.domain.board.position.Movement; import chess.domain.board.position.Path; import chess.domain.board.position.Position; +import chess.domain.piece.Color; +import chess.domain.piece.Piece; import java.util.List; import java.util.Map; diff --git a/src/main/java/chess/domain/piece/King.java b/src/main/java/chess/domain/piece/jumper/King.java similarity index 84% rename from src/main/java/chess/domain/piece/King.java rename to src/main/java/chess/domain/piece/jumper/King.java index 425006d9548..1178e9cde4f 100644 --- a/src/main/java/chess/domain/piece/King.java +++ b/src/main/java/chess/domain/piece/jumper/King.java @@ -1,7 +1,8 @@ -package chess.domain.piece; +package chess.domain.piece.jumper; import chess.domain.board.position.Movement; import chess.domain.board.position.Position; +import chess.domain.piece.Color; public class King extends JumperPiece { diff --git a/src/main/java/chess/domain/piece/Knight.java b/src/main/java/chess/domain/piece/jumper/Knight.java similarity index 91% rename from src/main/java/chess/domain/piece/Knight.java rename to src/main/java/chess/domain/piece/jumper/Knight.java index 40779207be0..1603e86e2f6 100644 --- a/src/main/java/chess/domain/piece/Knight.java +++ b/src/main/java/chess/domain/piece/jumper/Knight.java @@ -1,7 +1,8 @@ -package chess.domain.piece; +package chess.domain.piece.jumper; import chess.domain.board.position.Movement; import chess.domain.board.position.Position; +import chess.domain.piece.Color; public class Knight extends JumperPiece { diff --git a/src/main/java/chess/domain/piece/Pawn.java b/src/main/java/chess/domain/piece/pawn/Pawn.java similarity index 97% rename from src/main/java/chess/domain/piece/Pawn.java rename to src/main/java/chess/domain/piece/pawn/Pawn.java index d93e5b42634..d176be6e4cd 100644 --- a/src/main/java/chess/domain/piece/Pawn.java +++ b/src/main/java/chess/domain/piece/pawn/Pawn.java @@ -1,8 +1,10 @@ -package chess.domain.piece; +package chess.domain.piece.pawn; import chess.domain.board.position.Movement; import chess.domain.board.position.Path; import chess.domain.board.position.Position; +import chess.domain.piece.Color; +import chess.domain.piece.Piece; import java.util.List; import java.util.Map; diff --git a/src/main/java/chess/domain/piece/Bishop.java b/src/main/java/chess/domain/piece/slider/Bishop.java similarity index 62% rename from src/main/java/chess/domain/piece/Bishop.java rename to src/main/java/chess/domain/piece/slider/Bishop.java index 41f4c821461..2b88f3dd0f7 100644 --- a/src/main/java/chess/domain/piece/Bishop.java +++ b/src/main/java/chess/domain/piece/slider/Bishop.java @@ -1,4 +1,6 @@ -package chess.domain.piece; +package chess.domain.piece.slider; + +import chess.domain.piece.Color; public class Bishop extends SliderPiece { diff --git a/src/main/java/chess/domain/piece/Queen.java b/src/main/java/chess/domain/piece/slider/Queen.java similarity index 61% rename from src/main/java/chess/domain/piece/Queen.java rename to src/main/java/chess/domain/piece/slider/Queen.java index b1363c66d44..8029dfd8144 100644 --- a/src/main/java/chess/domain/piece/Queen.java +++ b/src/main/java/chess/domain/piece/slider/Queen.java @@ -1,4 +1,6 @@ -package chess.domain.piece; +package chess.domain.piece.slider; + +import chess.domain.piece.Color; public class Queen extends SliderPiece { diff --git a/src/main/java/chess/domain/piece/Rook.java b/src/main/java/chess/domain/piece/slider/Rook.java similarity index 61% rename from src/main/java/chess/domain/piece/Rook.java rename to src/main/java/chess/domain/piece/slider/Rook.java index 5621fefcdd3..3ff1d20feff 100644 --- a/src/main/java/chess/domain/piece/Rook.java +++ b/src/main/java/chess/domain/piece/slider/Rook.java @@ -1,4 +1,6 @@ -package chess.domain.piece; +package chess.domain.piece.slider; + +import chess.domain.piece.Color; public class Rook extends SliderPiece { diff --git a/src/main/java/chess/domain/piece/SliderPiece.java b/src/main/java/chess/domain/piece/slider/SliderPiece.java similarity index 94% rename from src/main/java/chess/domain/piece/SliderPiece.java rename to src/main/java/chess/domain/piece/slider/SliderPiece.java index 9700b44129c..c73be048266 100644 --- a/src/main/java/chess/domain/piece/SliderPiece.java +++ b/src/main/java/chess/domain/piece/slider/SliderPiece.java @@ -1,8 +1,10 @@ -package chess.domain.piece; +package chess.domain.piece.slider; import chess.domain.board.position.Movement; import chess.domain.board.position.Path; import chess.domain.board.position.Position; +import chess.domain.piece.Color; +import chess.domain.piece.Piece; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/chess/view/Command.java b/src/main/java/chess/view/Command.java index fba09ea860f..b0cfb8fc2c1 100644 --- a/src/main/java/chess/view/Command.java +++ b/src/main/java/chess/view/Command.java @@ -1,12 +1,13 @@ package chess.view; -import java.util.Arrays; - public enum Command { START("start"), MOVE("move"), - END("end"); + END("end"), + STATUS("status"), + NEW_GAME("1"), + LOAD_GAME("2"); private final String value; @@ -15,23 +16,30 @@ public enum Command { } public static boolean isEnd(String command) { - return Arrays.stream(values()) - .anyMatch(it -> it.value.equals(command) && command.equals(END.value)); + return END.value.equals(command); } public static boolean isMove(String command) { - return Arrays.stream(values()) - .anyMatch(it -> it.value.equals(command) && command.equals(MOVE.value)); + return MOVE.value.equals(command); } public static boolean isNotStart(String command) { - return Arrays.stream(values()) - .anyMatch(it -> it.value.equals(command) && !command.equals(START.value)); + return !START.value.equals(command); } public static boolean isNotAppropriate(String command) { - return Arrays.stream(values()) - .filter(it -> it != MOVE) - .noneMatch(it -> it.value.equals(command)); + return isNotStart(command) && !isEnd(command); + } + + public static boolean isStatus(final String command) { + return STATUS.value.equals(command); + } + + public static boolean isNewGame(final String command) { + return NEW_GAME.value.equals(command); + } + + public static boolean isExistedGame(final String command) { + return LOAD_GAME.value.equals(command); } } diff --git a/src/main/java/chess/view/InputView.java b/src/main/java/chess/view/InputView.java index 19cc789c582..6f7ed12d35a 100644 --- a/src/main/java/chess/view/InputView.java +++ b/src/main/java/chess/view/InputView.java @@ -1,5 +1,8 @@ package chess.view; +import chess.common.IndexCommand; +import chess.domain.board.position.PositionCache; + import java.util.Arrays; import java.util.List; import java.util.Scanner; @@ -14,25 +17,65 @@ public static String readStartCommand() { System.out.println("> 체스 게임을 시작합니다."); System.out.println("> 게임 시작 : start"); System.out.println("> 게임 종료 : end"); + System.out.println("> 게임 점수 확인 : status"); + System.out.println("end, status 를 입력하게 되면 게임이 저장됩니다."); System.out.println("> 게임 이동 : move source위치 target위치 - 예. move b2 b3"); final String command = scanner.nextLine(); + validateAppropriate(command); + + return command; + } + + private static void validateAppropriate(final String command) { if (Command.isNotAppropriate(command)) { throw new IllegalArgumentException("start 나 end 둘 중에 하나 입력해주세요."); } - - return command; } public static List readMoveCommand() { final List commands = Arrays.stream(scanner.nextLine().split(INPUT_COMMAND_DELIM)) .collect(Collectors.toList()); - if (commands.size() > 3) { - throw new IllegalArgumentException("잘못된 명령어입니다."); + if (isCommandStatusOrEnd(commands)) { + return commands; } + validateCommandSize(commands); + + final String sourcePosition = commands.get(IndexCommand.SOURCE_POSITION.value()); + final String targetPosition = commands.get(IndexCommand.TARGET_POSITION.value()); + + validateCanNotAccessPosition(sourcePosition, targetPosition); + return commands; } + + private static boolean isCommandStatusOrEnd(final List commands) { + return Command.isStatus(commands.get(IndexCommand.START_COMMAND_INDEX.value())) || + Command.isEnd(commands.get(IndexCommand.START_COMMAND_INDEX.value())); + } + + private static void validateCommandSize(final List commands) { + if (commands.size() > 3) { + throw new IllegalArgumentException("[명령어] [시작 위치] [도착 위치] 로 입력해주세요."); + } + } + + private static void validateCanNotAccessPosition(final String sourcePosition, final String targetPosition) { + if (PositionCache.isNotCaching(sourcePosition) || PositionCache.isNotCaching(targetPosition)) { + throw new IllegalArgumentException("접근할 수 없는 위치입니다."); + } + } + + public static String readNewGameCommand() { + return scanner.nextLine(); + } + + public static long readLoadGameCommand() { + final String command = scanner.nextLine(); + + return Long.parseLong(command); + } } diff --git a/src/main/java/chess/view/OutputView.java b/src/main/java/chess/view/OutputView.java index 9c2fac4130a..106304256a3 100644 --- a/src/main/java/chess/view/OutputView.java +++ b/src/main/java/chess/view/OutputView.java @@ -1,13 +1,15 @@ package chess.view; import chess.domain.board.position.Position; -import chess.domain.piece.Bishop; -import chess.domain.piece.King; -import chess.domain.piece.Knight; -import chess.domain.piece.Pawn; +import chess.domain.board.score.Score; +import chess.domain.piece.Color; import chess.domain.piece.Piece; -import chess.domain.piece.Queen; -import chess.domain.piece.Rook; +import chess.domain.piece.jumper.King; +import chess.domain.piece.jumper.Knight; +import chess.domain.piece.pawn.Pawn; +import chess.domain.piece.slider.Bishop; +import chess.domain.piece.slider.Queen; +import chess.domain.piece.slider.Rook; import java.util.ArrayList; import java.util.Collections; @@ -67,4 +69,27 @@ private static String formatPieceDisplay(final Piece piece) { } return pieceDisplay; } + + public static void printWinner(final Color color, final Score whiteScore, final Score blackScore) { + System.out.println(Color.WHITE.name() + " " + whiteScore.value()); + System.out.println(Color.BLACK.name() + " " + blackScore.value()); + + if (color.isNone()) { + System.out.println("무승부입니다."); + return; + } + + System.out.println("승자는 : " + color.name()); + } + + public static void printWinner(final Color color, final Score winnerScore) { + System.out.println("승자는 : " + color.name()); + System.out.println("점수는 : " + winnerScore.value()); + } + + public static void printGameCandidates(List gameIds) { + System.out.println(gameIds.stream() + .map(String::valueOf) + .collect(Collectors.joining(", "))); + } } diff --git a/src/main/resources/sql/schema.sql b/src/main/resources/sql/schema.sql new file mode 100644 index 00000000000..ebad34fc6e2 --- /dev/null +++ b/src/main/resources/sql/schema.sql @@ -0,0 +1,11 @@ +DROP TABLE IF EXISTS BOARD; + +CREATE TABLE BOARD +( + + BOARD_ID BIGINT AUTO_INCREMENT, + POSITION VARCHAR(1000) NOT NULL, + TURN VARCHAR(10) NOT NULL, + + PRIMARY KEY (BOARD_ID) +); diff --git a/src/test/java/chess/dao/BoardDaoTest.java b/src/test/java/chess/dao/BoardDaoTest.java new file mode 100644 index 00000000000..caf11c81ab6 --- /dev/null +++ b/src/test/java/chess/dao/BoardDaoTest.java @@ -0,0 +1,135 @@ +package chess.dao; + +import chess.domain.board.service.dto.BoardModifyRequest; +import chess.domain.board.service.dto.BoardRegisterRequest; +import chess.domain.board.service.dto.BoardSearchResponse; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.List; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class BoardDaoTest { + + private final BoardDao boardDao = new BoardDao(); + + @BeforeEach + void initDatabase() { + final String query = "INSERT INTO BOARD(POSITION, TURN) VALUES(?, ?)"; + + try (final Connection connection = MySqlManager.establishConnection(); + final PreparedStatement preparedStatement = connection.prepareStatement(query);) { + + preparedStatement.setString(1, "mock data1"); + preparedStatement.setString(2, "WHITE"); + preparedStatement.executeUpdate(); + + } catch (SQLException e) {} + + try (final Connection connection = MySqlManager.establishConnection(); + final PreparedStatement preparedStatement = connection.prepareStatement(query);) { + + preparedStatement.setString(1, "mock data2"); + preparedStatement.setString(2, "BLACK"); + preparedStatement.executeUpdate(); + + } catch (SQLException e) {} + } + + @AfterEach + void clearDatabase() { + final String query = "truncate BOARD"; + + try (final Connection connection = MySqlManager.establishConnection(); + final PreparedStatement preparedStatement = connection.prepareStatement(query);) { + + preparedStatement.executeUpdate(); + + } catch (SQLException e) {} + } + + @Test + @DisplayName("save() : board를 저장할 수 있다.") + void test_save() throws Exception { + //given + final String position = "King : 1 1, Queen : 1 2"; + final String turn = "WHITE"; + final BoardRegisterRequest boardRegisterRequest = new BoardRegisterRequest(position, turn); + + //when & then + final Long savedId = boardDao.save(boardRegisterRequest); + assertEquals(savedId, 3L); + } + + @Test + @DisplayName("findById() : board id 를 통해서 조회할 수 있다.") + void test_findById() throws Exception { + //given + final Long boardId = 2L; + + //when + Optional savedBoardDao = boardDao.findById(boardId); + + //then + assertAll( + () -> assertTrue(savedBoardDao.isPresent()), + () -> assertEquals(savedBoardDao.get().position(), "mock data2"), + () -> assertEquals(savedBoardDao.get().turn(), "BLACK") + ); + } + + @Test + @DisplayName("findAll() : 사용자가 참여한 board 를 모두 조회할 수 있다.") + void test_findAll() throws Exception { + //when + List boardSearchResponses = boardDao.findAll(); + + //then + assertEquals(2, boardSearchResponses.size()); + } + + @Test + @DisplayName("modifyById() : board id를 통해서 board를 수정할 수 있다.") + void test_modifyById() throws Exception { + //given + final Long boardId = 2L; + final String modifyingPosition = "modify data"; + final String turn = "BLACK"; + + final BoardModifyRequest boardModifyRequest = new BoardModifyRequest(boardId, modifyingPosition, turn); + + //when + boardDao.modifyById(boardModifyRequest); + final Optional modifiedBoard = boardDao.findById(boardId); + + //then/ + assertAll( + () -> assertTrue(modifiedBoard.isPresent()), + () -> assertEquals(modifiedBoard.get().position(), modifyingPosition), + () -> assertEquals(modifiedBoard.get().turn(), turn) + ); + } + + @Test + @DisplayName("deleteById() : board id를 통해서 board를 삭제할 수 있다.") + void test_deleteById() throws Exception { + //given + final Long boardId = 1L; + + //when + boardDao.deleteById(boardId); + final Optional savedBoard = boardDao.findById(boardId); + + //then + assertTrue(savedBoard.isEmpty()); + } +} diff --git a/src/test/java/chess/dao/MySqlManagerTest.java b/src/test/java/chess/dao/MySqlManagerTest.java new file mode 100644 index 00000000000..cbcfe66d53f --- /dev/null +++ b/src/test/java/chess/dao/MySqlManagerTest.java @@ -0,0 +1,11 @@ +package chess.dao; + +import org.junit.jupiter.api.Test; + +class MySqlManagerTest { + + @Test + void init_MySQL() throws Exception { + MySqlManager.initMySQL(); + } +} diff --git a/src/test/java/chess/domain/board/BoardTest.java b/src/test/java/chess/domain/board/BoardTest.java index 68806c48625..6e1d7e13540 100644 --- a/src/test/java/chess/domain/board/BoardTest.java +++ b/src/test/java/chess/domain/board/BoardTest.java @@ -1,13 +1,21 @@ package chess.domain.board; +import chess.domain.board.factory.BoardFactory; import chess.domain.board.position.Position; import chess.domain.piece.Color; +import chess.domain.piece.Piece; +import chess.helper.BoardFixture; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.Map; + import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; class BoardTest { @@ -16,7 +24,7 @@ class BoardTest { @BeforeEach void boardInit() { - board = new Board(new BoardFactory()); + board = Board.makeNewGame(new BoardFactory()); } @Test @@ -28,7 +36,7 @@ void test_move_empty_IllegalArgumentException() { final Position to = new Position(1, 1); //when & then - assertThatThrownBy(() -> board.move(emptyPosition, to, Color.WHITE)) + assertThatThrownBy(() -> board.move(emptyPosition, to)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("출발점에 말이 없습니다."); } @@ -42,7 +50,7 @@ void test_movePawn() { assertTrue(board.chessBoard().containsKey(from)); assertFalse(board.chessBoard().containsKey(to)); - board.move(from, to, Color.WHITE); + board.move(from, to); assertFalse(board.chessBoard().containsKey(from)); assertTrue(board.chessBoard().containsKey(to)); @@ -56,7 +64,7 @@ void test_move_validateObstacle_exception() throws Exception { final Position to = new Position(1, 3); //when & then - assertThatThrownBy(() -> board.move(from, to, Color.WHITE)) + assertThatThrownBy(() -> board.move(from, to)) .isInstanceOf(IllegalStateException.class) .hasMessage("중간에 다른 기물이 존재합니다."); } @@ -65,15 +73,51 @@ void test_move_validateObstacle_exception() throws Exception { @DisplayName("move() : 연속으로 같은 색의 말이 이동할 경우 IllegalArgumentException 가 밸상합니다.") void test_move_serialMove_IllegalArgumentException() throws Exception { //given - board.move(new Position(2, 2), new Position(2, 4), Color.WHITE); + board.move(new Position(2, 2), new Position(2, 4)); final Position from = new Position(2, 4); final Position to = new Position(2, 5); //when & then - assertThatThrownBy(() -> board.move(from, to, Color.BLACK)) + assertThatThrownBy(() -> board.move(from, to)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("차례에 맞는 말을 선택해 주세요"); } + + @Test + @DisplayName("bringBackPreviousGame() : 이전에 진행했던 게임을 다시 Board로 만들 수 있습니다.") + void test_bringBackPreviousGame() throws Exception { + //given + final Map board = BoardFixture.createBoard(); + final Turn turn = new Turn(Color.BLACK); + + //when + final Board previousGame = Board.bringBackPreviousGame(board, turn, 1L); + + final Map savedChessBoard = previousGame.chessBoard(); + final Turn savedTurn = previousGame.turn(); + + //then + assertAll( + () -> assertEquals(savedChessBoard, board), + () -> assertEquals(turn, savedTurn) + ); + } + + @Test + @DisplayName("makeNewGame() : 새로운 게임을 만들 수 있다.") + void test_makeNewGame() throws Exception { + //when + final Board newGame = Board.makeNewGame(new BoardFactory()); + + final Map newChessBoard = newGame.chessBoard(); + final Turn savedTurn = newGame.turn(); + + //then + assertAll( + () -> assertNotNull(newChessBoard), + () -> assertEquals(savedTurn, new Turn(Color.WHITE)) + ); + } } diff --git a/src/test/java/chess/domain/board/BoardFactoryTest.java b/src/test/java/chess/domain/board/factory/BoardFactoryTest.java similarity index 83% rename from src/test/java/chess/domain/board/BoardFactoryTest.java rename to src/test/java/chess/domain/board/factory/BoardFactoryTest.java index a6e4a42bfca..a3064d4370c 100644 --- a/src/test/java/chess/domain/board/BoardFactoryTest.java +++ b/src/test/java/chess/domain/board/factory/BoardFactoryTest.java @@ -1,13 +1,14 @@ -package chess.domain.board; +package chess.domain.board.factory; +import chess.domain.board.factory.BoardFactory; import chess.domain.board.position.Position; -import chess.domain.piece.Bishop; -import chess.domain.piece.King; -import chess.domain.piece.Knight; -import chess.domain.piece.Pawn; +import chess.domain.piece.slider.Bishop; +import chess.domain.piece.jumper.King; +import chess.domain.piece.jumper.Knight; +import chess.domain.piece.pawn.Pawn; import chess.domain.piece.Piece; -import chess.domain.piece.Queen; -import chess.domain.piece.Rook; +import chess.domain.piece.slider.Queen; +import chess.domain.piece.slider.Rook; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/chess/domain/board/position/ColumnTest.java b/src/test/java/chess/domain/board/position/ColumnTest.java index dd34562a733..40919a1ef62 100644 --- a/src/test/java/chess/domain/board/position/ColumnTest.java +++ b/src/test/java/chess/domain/board/position/ColumnTest.java @@ -5,8 +5,10 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; +import java.util.List; import java.util.NoSuchElementException; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -57,4 +59,15 @@ void test_from(final char value, final int result) throws Exception { //then assertEquals(convertedColumn, column); } + + @Test + @DisplayName("findPossibleColumnCandidates() : Column 이 될 수 있는 value 를 소문자로 구할 수 있다.") + void test_findPossibleColumnCandidates() throws Exception { + //when + final List possibleColumnCandidates = Column.findPossibleColumnCandidates(); + + //then + assertThat(possibleColumnCandidates).contains("a", "b", "c", "d", + "e", "f", "g", "h"); + } } diff --git a/src/test/java/chess/domain/board/position/PositionCacheTest.java b/src/test/java/chess/domain/board/position/PositionCacheTest.java new file mode 100644 index 00000000000..662b2c45ad9 --- /dev/null +++ b/src/test/java/chess/domain/board/position/PositionCacheTest.java @@ -0,0 +1,30 @@ +package chess.domain.board.position; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertFalse; + +class PositionCacheTest { + + @Test + @DisplayName("isCaching() : PositionCache에 값이 존재하는지 확인할 수 있다.") + void test_isCaching() throws Exception { + //given + final List positionCandidates = new ArrayList<>(); + + for (char column = 'a'; column <= 'h'; column++) { + for (int row = 1; row <= 8; row++) { + positionCandidates.add(String.valueOf(column) + row); + } + } + + //when & then + for (final String positionCandidate : positionCandidates) { + assertFalse(PositionCache.isNotCaching(positionCandidate)); + } + } +} diff --git a/src/test/java/chess/domain/board/position/RowTest.java b/src/test/java/chess/domain/board/position/RowTest.java index 2e5f8b43570..f898b3d4f17 100644 --- a/src/test/java/chess/domain/board/position/RowTest.java +++ b/src/test/java/chess/domain/board/position/RowTest.java @@ -5,8 +5,10 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; +import java.util.List; import java.util.NoSuchElementException; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -57,4 +59,14 @@ void test_from(final char value, final int result) throws Exception { //then assertEquals(convertedRow, row); } + + @Test + @DisplayName("findPossibleRowCandidates() : Row 가 될 수 있는 value 를 소문자로 구할 수 있다.") + void test_findPossibleRowCandidates() throws Exception { + //when + final List possibleRowCandidates = Row.findPossibleRowCandidates(); + + //then + assertThat(possibleRowCandidates).contains(1,2,3,4,5,6,7,8); + } } diff --git a/src/test/java/chess/domain/board/score/BoardScoreTest.java b/src/test/java/chess/domain/board/score/BoardScoreTest.java new file mode 100644 index 00000000000..cd28c5038e9 --- /dev/null +++ b/src/test/java/chess/domain/board/score/BoardScoreTest.java @@ -0,0 +1,45 @@ +package chess.domain.board.score; + +import chess.domain.board.score.BoardScore; +import chess.domain.board.score.Score; +import chess.domain.piece.Color; +import chess.helper.BoardFixture; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class BoardScoreTest { + + /** + * .KR..... 8 + * P.PB.... 7 + * .P..Q... 6 + * ........ 5 + * .....nq. 4 + * .....p.p 3 + * .....pp. 2 + * ....rk.. 1 + *

+ * 12345678 + */ + @Test + @DisplayName("calculateBoardScoreBy() : 색깔마다 체스 기물들의 점수 합을 모두 구할 수 있다.") + void test_calculateBoardScoreBy() throws Exception { + //given + final BoardScore boardScore = BoardScore.flatByColumnFrom(BoardFixture.createBoard()); + final Color black = Color.BLACK; + final Color white = Color.WHITE; + + //when + Score whitePieceScore = boardScore.calculateBoardScoreBy(white); + Score blackPieceScore = boardScore.calculateBoardScoreBy(black); + + //then + assertAll( + () -> assertEquals(whitePieceScore, Score.from(19.5)), + () -> assertEquals(blackPieceScore, Score.from(20)) + ); + } +} diff --git a/src/test/java/chess/domain/board/score/ColumnPieceTest.java b/src/test/java/chess/domain/board/score/ColumnPieceTest.java new file mode 100644 index 00000000000..37d0acded02 --- /dev/null +++ b/src/test/java/chess/domain/board/score/ColumnPieceTest.java @@ -0,0 +1,124 @@ +package chess.domain.board.score; + +import chess.domain.board.score.ColumnPiece; +import chess.domain.board.score.Score; +import chess.domain.piece.slider.Bishop; +import chess.domain.piece.Color; +import chess.domain.piece.jumper.King; +import chess.domain.piece.jumper.Knight; +import chess.domain.piece.pawn.Pawn; +import chess.domain.piece.slider.Queen; +import chess.domain.piece.slider.Rook; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.List; +import java.util.stream.Stream; + +import static chess.domain.piece.Color.BLACK; +import static chess.domain.piece.Color.WHITE; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class ColumnPieceTest { + + /** + * .KR..... 8 + * P.PB.... 7 + * .P..Q... 6 + * ........ 5 + * .....nq. 4 + * .....p.p 3 + * .....pp. 2 + * ....rk.. 1 + * 12345678 + */ + @ParameterizedTest + @MethodSource("calculateScore") + @DisplayName("calculatePiecesScore() : 주어진 색깔의 피스 기물들의 점수 합을 구할 수 있다.") + void test_calculatePiecesScore(final ColumnPiece columnPiece, + final Color color, + final Score result) throws Exception { + //when & then + assertEquals(columnPiece.calculatePiecesScore(color), result); + } + + static Stream calculateScore() { + + final ColumnPiece columnPiece1 = + new ColumnPiece( + List.of(new Pawn(WHITE), new Pawn(WHITE), + new Knight(WHITE), new King(WHITE) + ) + ); + + final Color color1 = WHITE; + final Score result1 = Score.from(3.5); + + final ColumnPiece columnPiece2 = new ColumnPiece( + List.of(new Queen(WHITE), new Pawn(WHITE)) + ); + + final Color color2 = WHITE; + final Score result2 = Score.from(10); + + final ColumnPiece columnPiece3 = new ColumnPiece( + List.of(new Pawn(WHITE)) + ); + + final Color color3 = WHITE; + final Score result3 = Score.from(1); + + final ColumnPiece columnPiece4 = new ColumnPiece( + List.of(new Queen(BLACK), new Rook(WHITE)) + ); + + final Color color4 = WHITE; + final Score result4 = Score.from(5); + + final Color color5 = BLACK; + final Score result5 = Score.from(9); + + final ColumnPiece columnPiece5 = new ColumnPiece( + List.of(new Bishop(BLACK)) + ); + + final Color color6 = BLACK; + final Score result6 = Score.from(3); + + final ColumnPiece columnPiece6 = new ColumnPiece( + List.of(new Rook(BLACK), new Pawn(BLACK)) + ); + + final Color color7 = BLACK; + final Score result7 = Score.from(6); + + final ColumnPiece columnPiece7 = new ColumnPiece( + List.of(new King(BLACK), new Pawn(BLACK)) + ); + + final Color color8 = BLACK; + final Score result8 = Score.from(1); + + final ColumnPiece columnPiece8 = new ColumnPiece( + List.of(new Pawn(BLACK)) + ); + + final Color color9 = BLACK; + final Score result9 = Score.from(1); + + + return Stream.of( + Arguments.of(columnPiece1, color1, result1), + Arguments.of(columnPiece2, color2, result2), + Arguments.of(columnPiece3, color3, result3), + Arguments.of(columnPiece4, color4, result4), + Arguments.of(columnPiece4, color5, result5), + Arguments.of(columnPiece5, color6, result6), + Arguments.of(columnPiece6, color7, result7), + Arguments.of(columnPiece7, color8, result8), + Arguments.of(columnPiece8, color9, result9) + ); + } +} diff --git a/src/test/java/chess/domain/board/score/ScoreTest.java b/src/test/java/chess/domain/board/score/ScoreTest.java new file mode 100644 index 00000000000..f893949f996 --- /dev/null +++ b/src/test/java/chess/domain/board/score/ScoreTest.java @@ -0,0 +1,63 @@ +package chess.domain.board.score; + +import chess.domain.board.score.Score; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ScoreTest { + + @ParameterizedTest + @CsvSource({ + "1,2,3", + "0,1,1", + "100000,3,100003" + }) + @DisplayName("plus() : Score끼리 더할 수 있다.") + void test_plus(final int value1, final int value2, final int resultValue) throws Exception { + //given + final Score score1 = Score.from(value1); + final Score score2 = Score.from(value2); + final Score result = Score.from(resultValue); + + //when & then + assertEquals(score1.plus(score2), result); + } + + @ParameterizedTest + @CsvSource({ + "1,2,2", + "0,1,0", + "100000,3,300000" + }) + @DisplayName("multiply() : Score에 value만큼 곱할 수 있다.") + void test_multiply(final int value1, final int repeat, final int resultValue) throws Exception { + //given + final Score score = Score.from(value1); + final Score result = Score.from(resultValue); + + //when & then + assertEquals(score.multiply(repeat), result); + } + + @ParameterizedTest + @CsvSource({ + "2,1", + "1,0", + "100000,3" + }) + @DisplayName("isGreaterThan(value) : score가 value 보다 크면 true 를 반환한다.") + void test_isGreaterThan(final int value1, final int value2) throws Exception { + //given + final Score score1 = Score.from(value1); + final Score score2 = Score.from(value2); + + //when & then + assertTrue(score1.isGreaterThan(score2)); + assertFalse(score2.isGreaterThan(score1)); + } +} diff --git a/src/test/java/chess/domain/board/search/BoardSearchTest.java b/src/test/java/chess/domain/board/search/BoardSearchTest.java new file mode 100644 index 00000000000..8048d0fb057 --- /dev/null +++ b/src/test/java/chess/domain/board/search/BoardSearchTest.java @@ -0,0 +1,26 @@ +package chess.domain.board.search; + +import chess.helper.BoardFixture; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class BoardSearchTest { + + @Test + @DisplayName("isKingDead() : King 이 죽으면 true를 반환한다.") + void test_isKingDead() throws Exception { + //given + final BoardSearch kingDeadBoardSearch = BoardSearch.countPiecePerClassTypeFrom(BoardFixture.createKingDeadBoard()); + final BoardSearch kingNotDeadBoardSearch = BoardSearch.countPiecePerClassTypeFrom(BoardFixture.createBoard()); + + //when & then + assertAll( + () -> assertTrue(kingDeadBoardSearch.isKingDead()), + () -> assertFalse(kingNotDeadBoardSearch.isKingDead()) + ); + } +} diff --git a/src/test/java/chess/domain/board/service/BoardCommandServiceTest.java b/src/test/java/chess/domain/board/service/BoardCommandServiceTest.java new file mode 100644 index 00000000000..fad4bb5adc7 --- /dev/null +++ b/src/test/java/chess/domain/board/service/BoardCommandServiceTest.java @@ -0,0 +1,125 @@ +package chess.domain.board.service; + +import chess.dao.BoardDao; +import chess.dao.MySqlManager; +import chess.domain.board.Board; +import chess.domain.board.Turn; +import chess.domain.board.factory.BoardFactory; +import chess.domain.board.position.Position; +import chess.domain.board.service.mapper.BoardMapper; +import chess.domain.piece.Color; +import chess.domain.piece.Piece; +import chess.domain.piece.jumper.King; +import chess.domain.piece.pawn.Pawn; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Map; +import java.util.NoSuchElementException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class BoardCommandServiceTest { + + private final BoardDao boardDao = new BoardDao(); + private final BoardMapper boardMapper = new BoardMapper(); + private final BoardCommandService boardCommandService = new BoardCommandService( + boardDao, boardMapper + ); + private final BoardQueryService boardQueryService = new BoardQueryService( + boardDao, boardMapper + ); + + @BeforeEach + void initializeData() { + boardDao.save( + new chess.domain.board.service.dto.BoardRegisterRequest("K : 1 7, P : 3 7, k : 4 7, p : 5 7", + "WHITE") + ); + + boardDao.save( + new chess.domain.board.service.dto.BoardRegisterRequest("P : 3 7, k : 4 7, p : 5 7", + "WHITE") + ); + } + + @AfterEach + void clearData() { + final String query = "truncate BOARD"; + + try (final Connection connection = MySqlManager.establishConnection(); + final PreparedStatement preparedStatement = connection.prepareStatement(query);) { + + preparedStatement.executeUpdate(); + + } catch (SQLException e) { + } + } + + @Test + @DisplayName("registerBoard() : board 를 저장할 수 있다.") + void test_registerBoard() throws Exception { + //given + final Board board = Board.makeNewGame(new BoardFactory()); + + //when + final Long savedId = boardCommandService.registerBoard(board); + + //then + assertEquals(3, savedId); + } + + @Test + @DisplayName("modifyBoard() : board 를 수정할 수 있다.") + void test_modifyBoard() throws Exception { + //given P : 3 7, k : 4 7, p : 5 7 + final Long boardId = 1L; + + final Map map = Map.of( + new Position(3, 7), new Pawn(Color.BLACK), + new Position(4, 7), new King(Color.WHITE), + new Position(5, 7), new Pawn(Color.WHITE) + ); + + final Board board = Board.bringBackPreviousGame(map, new Turn(Color.WHITE), boardId); + + //when + boardCommandService.modifyBoard(board); + + final Board savedBoard = boardQueryService.searchBoard(boardId); + + //then + assertAll( + () -> assertEquals(savedBoard.turn(), new Turn(Color.WHITE)), + () -> assertThat(savedBoard.chessBoard()) + .hasSize(3) + .containsKeys( + new Position(3, 7), + new Position(5, 7), + new Position(4, 7) + ) + ); + } + + @Test + @DisplayName("deleteBoard() : board 를 삭제할 수 있다.") + void test_deleteBoard() throws Exception { + //given + final Long boardId = 2L; + + //when + boardCommandService.deleteBoard(boardId); + + //then + assertThatThrownBy(() -> boardQueryService.searchBoard(boardId)) + .isInstanceOf(NoSuchElementException.class); + } +} diff --git a/src/test/java/chess/domain/board/service/BoardQueryServiceTest.java b/src/test/java/chess/domain/board/service/BoardQueryServiceTest.java new file mode 100644 index 00000000000..2552c82e04d --- /dev/null +++ b/src/test/java/chess/domain/board/service/BoardQueryServiceTest.java @@ -0,0 +1,88 @@ +package chess.domain.board.service; + +import chess.dao.BoardDao; +import chess.dao.MySqlManager; +import chess.domain.board.Board; +import chess.domain.board.Turn; +import chess.domain.board.position.Position; +import chess.domain.board.service.dto.BoardRegisterRequest; +import chess.domain.board.service.mapper.BoardMapper; +import chess.domain.piece.Color; +import chess.domain.piece.Piece; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class BoardQueryServiceTest { + + private final BoardDao boardDao = new BoardDao(); + private final BoardMapper boardMapper = new BoardMapper(); + private final BoardQueryService boardQueryService = new BoardQueryService( + boardDao, boardMapper + ); + + @BeforeEach + void initializeData() { + boardDao.save( + new BoardRegisterRequest("K : 1 7, P : 3 7, k : 4 7, p : 5 7", + "WHITE") + ); + + boardDao.save( + new BoardRegisterRequest("K : 1 7, P : 3 7, k : 4 7, p : 5 7", + "BLACK") + ); + } + + @AfterEach + void clearData() { + final String query = "truncate BOARD"; + + try (final Connection connection = MySqlManager.establishConnection(); + final PreparedStatement preparedStatement = connection.prepareStatement(query);) { + + preparedStatement.executeUpdate(); + + } catch (SQLException e) {} + } + + @Test + @DisplayName("searchBoard() : board id를 통해 chessBoard와 누구의 차례인지 알 수 있다.") + void test_searchBoard() throws Exception { + //given + final Long boardId = 1L; + + //when + final Board board = boardQueryService.searchBoard(boardId); + + final Map chessBoard = board.chessBoard(); + final Turn turn = board.turn(); + + //then + Assertions.assertAll( + () -> assertEquals(turn, new Turn(Color.WHITE)), + () -> assertThat(chessBoard).hasSize(4) + ); + } + + @Test + @DisplayName("searchAllBoards() : 사용자가 참여하고 있는 모든 Board를 조회할 수 있다.") + void test_searchAllBoards() throws Exception { + //when + List ids = boardQueryService.searchAllBoards(); + + //then + assertThat(ids).hasSize(2); + } +} diff --git a/src/test/java/chess/domain/board/service/mapper/BoardMapperTest.java b/src/test/java/chess/domain/board/service/mapper/BoardMapperTest.java new file mode 100644 index 00000000000..37d65d60b0f --- /dev/null +++ b/src/test/java/chess/domain/board/service/mapper/BoardMapperTest.java @@ -0,0 +1,95 @@ +package chess.domain.board.service.mapper; + +import chess.domain.board.Board; +import chess.domain.board.Turn; +import chess.domain.board.position.Position; +import chess.domain.board.service.dto.BoardRegisterRequest; +import chess.domain.piece.Color; +import chess.domain.piece.Piece; +import chess.domain.piece.jumper.King; +import chess.domain.piece.pawn.Pawn; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.Map; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class BoardMapperTest { + + private final BoardMapper boardMapper = new BoardMapper(); + + @Test + @DisplayName("mapToBoardRegisterRequestFrom() : Board 를 위치를 가지는 String으로 mapping 시킬 수 있다. ") + void test_mapToBoardRegisterRequestFrom() throws Exception { + //given + final Board board = Board.bringBackPreviousGame( + Map.of(new Position(1, 7), new King(Color.BLACK), + new Position(3, 7), new Pawn(Color.BLACK), + new Position(4, 7), new King(Color.WHITE), + new Position(5, 7), new Pawn(Color.WHITE) + ), new Turn(Color.WHITE), 1L); + + //when + //"p:5 7,k:4 7,P:3 7,K:1 7" + final BoardRegisterRequest boardRegisterRequest = + boardMapper.mapToBoardRegisterRequestFrom(board); + + System.out.println(boardRegisterRequest.position()); + + Map> resultMap = + + Arrays.stream(boardRegisterRequest.position().split(",")) + .map(s -> s.split(":")) + .collect(Collectors.toMap( + arr -> new Position( + Integer.parseInt(arr[1].trim().split(" ")[0]), + Integer.parseInt( + arr[1].trim().split(" ")[1])), + arr -> PieceInitialMapping.mapToClassTypeFrom(arr[0].trim()) + )); + + //then + assertAll( + () -> assertEquals(4, resultMap.size()), + () -> assertEquals(resultMap.get(new Position(1, 7)), King.class), + () -> assertEquals(resultMap.get(new Position(3, 7)), Pawn.class), + () -> assertEquals(resultMap.get(new Position(5, 7)), Pawn.class), + () -> assertEquals(resultMap.get(new Position(4, 7)), King.class), + () -> assertEquals(boardRegisterRequest.turn(), Color.WHITE.name()) + ); + + } + + @Test + @DisplayName("mapToBoardSearchResponseFrom() : 위치와 차례를 String을 Board로 변환시킬 수 있다.") + void test_mapToBoardSearchResponseFrom() throws Exception { + //given + //"p:5 7,k:4 7,P:3 7,K:1 7" + final String position = "p:5 7,k:4 7,P:3 7,K:1 7"; + final String turn = "WHITE"; + + //when + Board board = boardMapper.mapToBoardSearchResponseFrom(position, turn, 1L); + + //then + final Map chessBoard = board.chessBoard(); + final Turn savedTurn = board.turn(); + + assertAll( + () -> assertThat(chessBoard) + .hasSize(4) + .containsKeys(new Position(1, 7), + new Position(3, 7), + new Position(5, 7), + new Position(4, 7)), + + () -> assertEquals(savedTurn, new Turn(Color.WHITE)) + ); + } +} + diff --git a/src/test/java/chess/domain/board/service/mapper/PieceInitialMappingTest.java b/src/test/java/chess/domain/board/service/mapper/PieceInitialMappingTest.java new file mode 100644 index 00000000000..e0c40f1c20e --- /dev/null +++ b/src/test/java/chess/domain/board/service/mapper/PieceInitialMappingTest.java @@ -0,0 +1,72 @@ +package chess.domain.board.service.mapper; + +import chess.domain.piece.Color; +import chess.domain.piece.Piece; +import chess.domain.piece.jumper.King; +import chess.domain.piece.slider.Queen; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class PieceInitialMappingTest { + + @Test + @DisplayName("mapToPieceInitialFrom() : Piece를 통해서 Piece 이니셜 알파벳을 알 수 있다.") + void test_mapToPieceInitialFrom() throws Exception { + //given + final Piece whiteKing = new King(Color.WHITE); + final Piece blackKing = new King(Color.BLACK); + + //when + final String whiteKingInitial = PieceInitialMapping.mapToPieceInitialFrom(whiteKing); + final String blackKingInitial = PieceInitialMapping.mapToPieceInitialFrom(blackKing); + + //then + assertAll( + () -> assertEquals(whiteKingInitial, "k"), + () -> assertEquals(blackKingInitial, "K") + ); + } + + @Test + @DisplayName("mapToClassTypeFrom() : Piece initial 을 통해 클래스 타입을 알 수 있다.") + void test_mapToClassTypeFrom() throws Exception { + //given + final String whiteQueenInitial = "q"; + final String blackKingInitial = "K"; + + //when + final Class queenClass = PieceInitialMapping.mapToClassTypeFrom(whiteQueenInitial); + final Class kingClass = PieceInitialMapping.mapToClassTypeFrom(blackKingInitial); + + //then + assertAll( + () -> assertEquals(queenClass, Queen.class), + () -> assertEquals(kingClass, King.class) + ); + } + + @Test + @DisplayName("mapToPieceFrom() : Piece initial 을 통해 Piece 를 생성할 수 있따.") + void test_mapToPieceFrom() throws Exception { + //given + final String whiteQueenInitial = "q"; + final String blackKingInitial = "K"; + + //when + final Piece queen = PieceInitialMapping.mapToPieceFrom(whiteQueenInitial); + final Piece king = PieceInitialMapping.mapToPieceFrom(blackKingInitial); + + //then + assertAll( + () -> assertEquals(queen.getClass(), Queen.class), + () -> assertFalse(queen.isBlack()), + () -> assertEquals(king.getClass(), King.class), + () -> assertTrue(king.isBlack()) + ); + } +} diff --git a/src/test/java/chess/domain/piece/KingTest.java b/src/test/java/chess/domain/piece/jumper/KingTest.java similarity index 95% rename from src/test/java/chess/domain/piece/KingTest.java rename to src/test/java/chess/domain/piece/jumper/KingTest.java index 10dbded84c3..7603d4bc7cb 100644 --- a/src/test/java/chess/domain/piece/KingTest.java +++ b/src/test/java/chess/domain/piece/jumper/KingTest.java @@ -1,7 +1,10 @@ -package chess.domain.piece; +package chess.domain.piece.jumper; import chess.domain.board.position.Path; import chess.domain.board.position.Position; +import chess.domain.piece.Color; +import chess.domain.piece.Piece; +import chess.domain.piece.slider.Queen; import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/chess/domain/piece/KnightTest.java b/src/test/java/chess/domain/piece/jumper/KnightTest.java similarity index 90% rename from src/test/java/chess/domain/piece/KnightTest.java rename to src/test/java/chess/domain/piece/jumper/KnightTest.java index 2ddf4170f99..3d30e93578b 100644 --- a/src/test/java/chess/domain/piece/KnightTest.java +++ b/src/test/java/chess/domain/piece/jumper/KnightTest.java @@ -1,7 +1,10 @@ -package chess.domain.piece; +package chess.domain.piece.jumper; import chess.domain.board.position.Path; import chess.domain.board.position.Position; +import chess.domain.piece.Color; +import chess.domain.piece.Piece; +import chess.domain.piece.jumper.Knight; import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/chess/domain/piece/PawnTest.java b/src/test/java/chess/domain/piece/pawn/PawnTest.java similarity index 97% rename from src/test/java/chess/domain/piece/PawnTest.java rename to src/test/java/chess/domain/piece/pawn/PawnTest.java index b4ae39ff39a..973428d92ce 100644 --- a/src/test/java/chess/domain/piece/PawnTest.java +++ b/src/test/java/chess/domain/piece/pawn/PawnTest.java @@ -1,7 +1,9 @@ -package chess.domain.piece; +package chess.domain.piece.pawn; import chess.domain.board.position.Path; import chess.domain.board.position.Position; +import chess.domain.piece.Color; +import chess.domain.piece.Piece; import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/chess/domain/piece/BishopTest.java b/src/test/java/chess/domain/piece/slider/BishopTest.java similarity index 93% rename from src/test/java/chess/domain/piece/BishopTest.java rename to src/test/java/chess/domain/piece/slider/BishopTest.java index acdc8cafacc..ccc013d382c 100644 --- a/src/test/java/chess/domain/piece/BishopTest.java +++ b/src/test/java/chess/domain/piece/slider/BishopTest.java @@ -1,7 +1,11 @@ -package chess.domain.piece; +package chess.domain.piece.slider; import chess.domain.board.position.Path; import chess.domain.board.position.Position; +import chess.domain.piece.Color; +import chess.domain.piece.Piece; +import chess.domain.piece.jumper.King; +import chess.domain.piece.slider.Bishop; import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/chess/domain/piece/QueenTest.java b/src/test/java/chess/domain/piece/slider/QueenTest.java similarity index 95% rename from src/test/java/chess/domain/piece/QueenTest.java rename to src/test/java/chess/domain/piece/slider/QueenTest.java index 5740f566c6a..b4fa8899bbf 100644 --- a/src/test/java/chess/domain/piece/QueenTest.java +++ b/src/test/java/chess/domain/piece/slider/QueenTest.java @@ -1,7 +1,10 @@ -package chess.domain.piece; +package chess.domain.piece.slider; import chess.domain.board.position.Path; import chess.domain.board.position.Position; +import chess.domain.piece.Color; +import chess.domain.piece.Piece; +import chess.domain.piece.jumper.King; import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/chess/domain/piece/RookTest.java b/src/test/java/chess/domain/piece/slider/RookTest.java similarity index 94% rename from src/test/java/chess/domain/piece/RookTest.java rename to src/test/java/chess/domain/piece/slider/RookTest.java index c6c71fd6798..40a616dcc63 100644 --- a/src/test/java/chess/domain/piece/RookTest.java +++ b/src/test/java/chess/domain/piece/slider/RookTest.java @@ -1,7 +1,11 @@ -package chess.domain.piece; +package chess.domain.piece.slider; import chess.domain.board.position.Path; import chess.domain.board.position.Position; +import chess.domain.piece.Color; +import chess.domain.piece.Piece; +import chess.domain.piece.jumper.King; +import chess.domain.piece.slider.Rook; import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/chess/helper/BoardFixture.java b/src/test/java/chess/helper/BoardFixture.java new file mode 100644 index 00000000000..49405c70b43 --- /dev/null +++ b/src/test/java/chess/helper/BoardFixture.java @@ -0,0 +1,99 @@ +package chess.helper; + +import chess.domain.board.position.Position; +import chess.domain.piece.slider.Bishop; +import chess.domain.piece.Color; +import chess.domain.piece.jumper.King; +import chess.domain.piece.jumper.Knight; +import chess.domain.piece.pawn.Pawn; +import chess.domain.piece.Piece; +import chess.domain.piece.slider.Queen; +import chess.domain.piece.slider.Rook; + +import java.util.HashMap; +import java.util.Map; + +public class BoardFixture { + + /** + * .KR..... 8 + * P.PB.... 7 + * .P..Q... 6 + * ........ 5 + * .....nq. 4 + * .....p.p 3 + * .....pp. 2 + * ....rk.. 1 + * + * 12345678 + */ + + public static Map createBoard() { + Map map = new HashMap<>(); + + final Map map1 = Map.of( + new Position(5, 1), new Rook(Color.WHITE), + new Position(6, 1), new King(Color.WHITE), + new Position(6, 2), new Pawn(Color.WHITE), + new Position(7, 2), new Pawn(Color.WHITE), + new Position(6, 3), new Pawn(Color.WHITE), + new Position(8, 3), new Pawn(Color.WHITE), + new Position(6, 4), new Knight(Color.WHITE), + new Position(7, 4), new Queen(Color.WHITE), + new Position(2, 6), new Pawn(Color.BLACK), + new Position(5, 6), new Queen(Color.BLACK) + ); + + final Map map2 = Map.of(new Position(1, 7), new Pawn(Color.BLACK), + new Position(3, 7), new Pawn(Color.BLACK), + new Position(4, 7), new Bishop(Color.BLACK), + new Position(2, 8), new King(Color.BLACK), + new Position(3, 8), new Rook(Color.BLACK)); + + + map.putAll(map1); + map.putAll(map2); + + return map; + } + + /** + * .KR..... 8 + * P.PB.... 7 + * .P..Q... 6 + * ........ 5 + * .....nq. 4 + * .....p.p 3 + * .....pp. 2 + * ....r... 1 + * + * 12345678 + */ + public static Map createKingDeadBoard() { + Map map = new HashMap<>(); + + final Map map1 = Map.of( + new Position(5, 1), new Rook(Color.WHITE), + new Position(6, 2), new Pawn(Color.WHITE), + new Position(7, 2), new Pawn(Color.WHITE), + new Position(6, 3), new Pawn(Color.WHITE), + new Position(8, 3), new Pawn(Color.WHITE), + new Position(6, 4), new Knight(Color.WHITE), + new Position(7, 4), new Queen(Color.WHITE), + new Position(2, 6), new Pawn(Color.BLACK), + new Position(5, 6), new Queen(Color.BLACK) + ); + + final Map map2 = Map.of(new Position(1, 7), new Pawn(Color.BLACK), + new Position(3, 7), new Pawn(Color.BLACK), + new Position(4, 7), new Bishop(Color.BLACK), + new Position(2, 8), new King(Color.BLACK), + new Position(3, 8), new Rook(Color.BLACK)); + + + map.putAll(map1); + map.putAll(map2); + + return map; + } +} diff --git a/src/test/java/chess/view/CommandTest.java b/src/test/java/chess/view/CommandTest.java index 5981cf9cd0d..901a3b4bbe9 100644 --- a/src/test/java/chess/view/CommandTest.java +++ b/src/test/java/chess/view/CommandTest.java @@ -8,7 +8,6 @@ class CommandTest { - @Test @DisplayName("isEnd() : end 명령어가 들어오면 true를 반환한다.") void test_isFinish() throws Exception { @@ -46,4 +45,16 @@ void test_isNotStart() throws Exception { assertTrue(Command.isNotStart(command2)); assertFalse(Command.isNotStart(command1)); } + + @Test + @DisplayName("isStatus() : status 명령어가 들어오면 true를 반환한다.") + void test_isStatus() throws Exception { + //given + String command1 = "status"; + String command2 = "move"; + + //when & then + assertTrue(Command.isStatus(command1)); + assertFalse(Command.isStatus(command2)); + } }