From b63b1e3772e4799b50102ea715b5fb25cf5dfb80 Mon Sep 17 00:00:00 2001 From: jiwon Date: Fri, 24 Mar 2023 00:33:30 +0900 Subject: [PATCH 01/76] =?UTF-8?q?feat:=20service=20layer=EB=A5=BC=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=ED=95=98=EA=B3=A0=20dto=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20static=20mapper=20=ED=81=B4=EB=9E=98=EC=8A=A4?= =?UTF-8?q?=EB=A5=BC=20=EC=83=9D=EC=84=B1=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/ChessApplication.java | 8 +---- .../java/chess/controller/ChessHandler.java | 10 ++---- .../mapper/ChessBoardDtoMapper.java | 23 ++++++++++++++ .../mapper/PieceDtoMapper.java} | 6 ++-- .../controller/mapper/PositionDtoMapper.java | 10 ++++++ .../java/chess/service/ChessBoardService.java | 31 ------------------- .../java/chess/service/PositionService.java | 10 ------ .../mapper/ChessBoardDtoMapperTest.java} | 8 ++--- .../mapper/PieceDtoMapperTest.java} | 8 ++--- .../mapper/PositionDtoMapperTest.java} | 8 ++--- 10 files changed, 50 insertions(+), 72 deletions(-) create mode 100644 src/main/java/chess/controller/mapper/ChessBoardDtoMapper.java rename src/main/java/chess/{service/PieceService.java => controller/mapper/PieceDtoMapper.java} (56%) create mode 100644 src/main/java/chess/controller/mapper/PositionDtoMapper.java delete mode 100644 src/main/java/chess/service/ChessBoardService.java delete mode 100644 src/main/java/chess/service/PositionService.java rename src/test/java/chess/{service/ChessBoardServiceTest.java => controller/mapper/ChessBoardDtoMapperTest.java} (71%) rename src/test/java/chess/{service/PieceServiceTest.java => controller/mapper/PieceDtoMapperTest.java} (82%) rename src/test/java/chess/{service/PositionServiceTest.java => controller/mapper/PositionDtoMapperTest.java} (76%) diff --git a/src/main/java/chess/ChessApplication.java b/src/main/java/chess/ChessApplication.java index b33c92c9651..03f68f40320 100644 --- a/src/main/java/chess/ChessApplication.java +++ b/src/main/java/chess/ChessApplication.java @@ -1,16 +1,10 @@ package chess; import chess.controller.ChessHandler; -import chess.service.ChessBoardService; -import chess.service.PieceService; -import chess.service.PositionService; public final class ChessApplication { public static void main(String[] args) { - final PieceService pieceService = new PieceService(); - final PositionService positionService = new PositionService(); - final ChessBoardService chessBoardService = new ChessBoardService(pieceService, positionService); - final ChessHandler chessHandler = new ChessHandler(chessBoardService); + final ChessHandler chessHandler = new ChessHandler(); chessHandler.run(); } } diff --git a/src/main/java/chess/controller/ChessHandler.java b/src/main/java/chess/controller/ChessHandler.java index 36fbfee4ecb..07d7a7324d5 100644 --- a/src/main/java/chess/controller/ChessHandler.java +++ b/src/main/java/chess/controller/ChessHandler.java @@ -1,9 +1,9 @@ package chess.controller; +import chess.controller.mapper.ChessBoardDtoMapper; import chess.controller.status.Controller; import chess.controller.status.StartController; import chess.domain.chess.ChessGame; -import chess.service.ChessBoardService; import chess.view.InputView; import chess.view.OutputView; @@ -11,12 +11,6 @@ public final class ChessHandler { - private final ChessBoardService chessBoardService; - - public ChessHandler(final ChessBoardService chessBoardService) { - this.chessBoardService = chessBoardService; - } - public void run() { OutputView.printStartMessage(); final ChessGame chessGame = new ChessGame(); @@ -36,7 +30,7 @@ private Controller play(final ChessGame chessGame, Controller controller) { final Command command = Command.findCommand(commands); controller = controller.checkCommand(command, () -> OutputView.printBoard( - chessBoardService.createChessBoardDto(chessGame.getChessBoard()) + ChessBoardDtoMapper.createChessBoardDto(chessGame.getChessBoard()) )); return controller; } catch (IllegalArgumentException e) { diff --git a/src/main/java/chess/controller/mapper/ChessBoardDtoMapper.java b/src/main/java/chess/controller/mapper/ChessBoardDtoMapper.java new file mode 100644 index 00000000000..adc7e57379d --- /dev/null +++ b/src/main/java/chess/controller/mapper/ChessBoardDtoMapper.java @@ -0,0 +1,23 @@ +package chess.controller.mapper; + +import chess.controller.dto.ChessBoardDto; +import chess.controller.dto.PieceDto; +import chess.controller.dto.PositionDto; +import chess.domain.piece.Piece; +import chess.domain.piece.move.Position; + +import java.util.HashMap; +import java.util.Map; + +public final class ChessBoardDtoMapper { + + public static ChessBoardDto createChessBoardDto(final Map chessBoard) { + final Map boardDto = new HashMap<>(); + for (Position position : chessBoard.keySet()) { + boardDto.put( + PositionDtoMapper.createPositionDto(position.getRank(), position.getFile()), + PieceDtoMapper.createPieceDto(chessBoard.get(position))); + } + return new ChessBoardDto(boardDto); + } +} diff --git a/src/main/java/chess/service/PieceService.java b/src/main/java/chess/controller/mapper/PieceDtoMapper.java similarity index 56% rename from src/main/java/chess/service/PieceService.java rename to src/main/java/chess/controller/mapper/PieceDtoMapper.java index c5e9340a4d9..0f0e3aeec1b 100644 --- a/src/main/java/chess/service/PieceService.java +++ b/src/main/java/chess/controller/mapper/PieceDtoMapper.java @@ -1,11 +1,11 @@ -package chess.service; +package chess.controller.mapper; import chess.controller.dto.PieceDto; import chess.domain.piece.Piece; -public final class PieceService { +public final class PieceDtoMapper { - public PieceDto createPieceDto(final Piece piece) { + public static PieceDto createPieceDto(final Piece piece) { return new PieceDto(piece.getPieceType().name(), piece.getCampType().name()); } } diff --git a/src/main/java/chess/controller/mapper/PositionDtoMapper.java b/src/main/java/chess/controller/mapper/PositionDtoMapper.java new file mode 100644 index 00000000000..ea5aae6e26d --- /dev/null +++ b/src/main/java/chess/controller/mapper/PositionDtoMapper.java @@ -0,0 +1,10 @@ +package chess.controller.mapper; + +import chess.controller.dto.PositionDto; + +public final class PositionDtoMapper { + + public static PositionDto createPositionDto(final int rank, final int file) { + return new PositionDto(rank, file); + } +} diff --git a/src/main/java/chess/service/ChessBoardService.java b/src/main/java/chess/service/ChessBoardService.java deleted file mode 100644 index 28ed1b740eb..00000000000 --- a/src/main/java/chess/service/ChessBoardService.java +++ /dev/null @@ -1,31 +0,0 @@ -package chess.service; - -import chess.controller.dto.ChessBoardDto; -import chess.controller.dto.PieceDto; -import chess.controller.dto.PositionDto; -import chess.domain.piece.Piece; -import chess.domain.piece.move.Position; - -import java.util.HashMap; -import java.util.Map; - -public final class ChessBoardService { - - private final PieceService pieceService; - private final PositionService positionService; - - public ChessBoardService(final PieceService pieceService, final PositionService positionService) { - this.pieceService = pieceService; - this.positionService = positionService; - } - - public ChessBoardDto createChessBoardDto(final Map chessBoard) { - final Map boardDto = new HashMap<>(); - for (Position position : chessBoard.keySet()) { - boardDto.put( - positionService.createPositionDto(position.getRank(), position.getFile()), - pieceService.createPieceDto(chessBoard.get(position))); - } - return new ChessBoardDto(boardDto); - } -} diff --git a/src/main/java/chess/service/PositionService.java b/src/main/java/chess/service/PositionService.java deleted file mode 100644 index 652e97340a4..00000000000 --- a/src/main/java/chess/service/PositionService.java +++ /dev/null @@ -1,10 +0,0 @@ -package chess.service; - -import chess.controller.dto.PositionDto; - -public final class PositionService { - - public PositionDto createPositionDto(final int rank, final int file) { - return new PositionDto(rank, file); - } -} diff --git a/src/test/java/chess/service/ChessBoardServiceTest.java b/src/test/java/chess/controller/mapper/ChessBoardDtoMapperTest.java similarity index 71% rename from src/test/java/chess/service/ChessBoardServiceTest.java rename to src/test/java/chess/controller/mapper/ChessBoardDtoMapperTest.java index 2074b5be104..7a332054500 100644 --- a/src/test/java/chess/service/ChessBoardServiceTest.java +++ b/src/test/java/chess/controller/mapper/ChessBoardDtoMapperTest.java @@ -1,4 +1,4 @@ -package chess.service; +package chess.controller.mapper; import chess.controller.dto.ChessBoardDto; import chess.domain.chess.ChessGame; @@ -8,19 +8,17 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -class ChessBoardServiceTest { +class ChessBoardDtoMapperTest { @Test @DisplayName("체스판 정보가 주어지면, 체스판 dto를 생성한다.") void createChessBoardDto() { // given - final ChessBoardService chessBoardService = new ChessBoardService( - new PieceService(), new PositionService()); final ChessGame chessGame = new ChessGame(); // when, then final ChessBoardDto chessBoardDto = assertDoesNotThrow(() -> - chessBoardService.createChessBoardDto(chessGame.getChessBoard())); + ChessBoardDtoMapper.createChessBoardDto(chessGame.getChessBoard())); assertThat(chessBoardDto) .isInstanceOf(ChessBoardDto.class); } diff --git a/src/test/java/chess/service/PieceServiceTest.java b/src/test/java/chess/controller/mapper/PieceDtoMapperTest.java similarity index 82% rename from src/test/java/chess/service/PieceServiceTest.java rename to src/test/java/chess/controller/mapper/PieceDtoMapperTest.java index d4cd6f34ce4..da82ff9dbae 100644 --- a/src/test/java/chess/service/PieceServiceTest.java +++ b/src/test/java/chess/controller/mapper/PieceDtoMapperTest.java @@ -1,4 +1,4 @@ -package chess.service; +package chess.controller.mapper; import chess.controller.dto.PieceDto; import chess.domain.chess.CampType; @@ -11,17 +11,17 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -class PieceServiceTest { +class PieceDtoMapperTest { @Test @DisplayName("체스말 정보가 주어지면, 체스말에 대한 dto를 생성한다.") void createPieceDto() { // given - final PieceService pieceService = new PieceService(); + final PieceDtoMapper pieceDtoMapper = new PieceDtoMapper(); final Piece piece = new Piece(PieceType.ROOK, CampType.WHITE, new Rook()); // when, then - final PieceDto pieceDto = assertDoesNotThrow(() -> pieceService.createPieceDto(piece)); + final PieceDto pieceDto = assertDoesNotThrow(() -> pieceDtoMapper.createPieceDto(piece)); assertThat(pieceDto) .isInstanceOf(PieceDto.class); } diff --git a/src/test/java/chess/service/PositionServiceTest.java b/src/test/java/chess/controller/mapper/PositionDtoMapperTest.java similarity index 76% rename from src/test/java/chess/service/PositionServiceTest.java rename to src/test/java/chess/controller/mapper/PositionDtoMapperTest.java index 20d0405416d..318ffd1b9c4 100644 --- a/src/test/java/chess/service/PositionServiceTest.java +++ b/src/test/java/chess/controller/mapper/PositionDtoMapperTest.java @@ -1,4 +1,4 @@ -package chess.service; +package chess.controller.mapper; import chess.controller.dto.PositionDto; import org.junit.jupiter.api.DisplayName; @@ -7,18 +7,18 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -class PositionServiceTest { +class PositionDtoMapperTest { @Test @DisplayName("rank, file이 주어지면 위치에 대한 dto를 생성한다.") void createPositionDto() { // given - final PositionService positionService = new PositionService(); + final PositionDtoMapper positionDtoMapper = new PositionDtoMapper(); final int rank = 3; final int file = 3; // when, then - final PositionDto positionDto = assertDoesNotThrow(() -> positionService.createPositionDto(rank, file)); + final PositionDto positionDto = assertDoesNotThrow(() -> positionDtoMapper.createPositionDto(rank, file)); assertThat(positionDto) .isInstanceOf(PositionDto.class); } From 442729185cc06f12f8af5157a1af1d9bf55643a8 Mon Sep 17 00:00:00 2001 From: jiwon Date: Fri, 24 Mar 2023 00:34:25 +0900 Subject: [PATCH 02/76] =?UTF-8?q?fix:=20=EC=95=84=EA=B5=B0=20=EA=B8=B0?= =?UTF-8?q?=EB=AC=BC=EC=9D=B8=EC=A7=80=20=EA=B2=80=EC=A6=9D=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5=EC=97=90=20=EB=8C=80=ED=95=B4=20?= =?UTF-8?q?=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D=20=EB=A1=9C=EC=A7=81=EC=9D=84=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/domain/chess/ChessGame.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/chess/domain/chess/ChessGame.java b/src/main/java/chess/domain/chess/ChessGame.java index d469240e566..c325d900d02 100644 --- a/src/main/java/chess/domain/chess/ChessGame.java +++ b/src/main/java/chess/domain/chess/ChessGame.java @@ -48,7 +48,6 @@ private void validateTargetSameCamp(final Position target) { if (!chessBoard.contains(target)) { return; } - validatePieceExistence(target); final Piece piece = chessBoard.getPiece(target); if (piece.isSameCamp(currentCamp)) { throw new IllegalArgumentException("아군 기물이 있는 곳으로 이동할 수 없습니다."); From fb8682fe4b1992ed8aa419eb8b612ca4777f6dd2 Mon Sep 17 00:00:00 2001 From: jiwon Date: Fri, 24 Mar 2023 10:44:22 +0900 Subject: [PATCH 03/76] =?UTF-8?q?feat:=20=EC=A0=90=EC=88=98=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=B4=20=EA=B4=80=EB=A6=AC=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A5=BC=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 16 ++++++++++++++++ .../java/chess/domain/piece/PieceType.java | 18 ++++++++++++------ src/main/java/chess/domain/piece/Score.java | 9 +++++++++ 3 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 src/main/java/chess/domain/piece/Score.java diff --git a/README.md b/README.md index aa00cd76fe3..863f585aa26 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,17 @@ ### ChessGame - [x] 체스 게임을 진행한다. +- [ ] 현재 차례인 진영이 다른 진영의 킹을 잡았을 때 게임을 종료한다. + - [ ] 현재 차례인 진영이 승리한 진영이 된다. + +### Score + +- [x] 점수에 대해서 관리한다. + +### ChessScoreCalculator + +- [ ] 체스 게임의 점수에 대해서 계산한다. +- [ ] 같은 세로줄에 같은 진영의 폰이 있는지 확인한다. ### CampType @@ -36,6 +47,7 @@ - [x] 체스말의 종류를 관리한다. - [x] 특정 체스말이 시작 위치에서 종료 위치까지 이동 가능한지 판단한다. +- [ ] 각 체스말의 점수에 대해 관리한다. ### Position @@ -142,6 +154,10 @@ - [x] 사용자가 입력한 명령어가 Move라면 예외를 발생시키고, End라면 종료한다. - [x] 현재 게임이 실행 중인지 판단한다. +### StatusController + +- [ ] 각 진영의 점수와 이긴 진영을 출력한다. + ### PieceName - [x] 체스말의 종류에 따라 체스말의 이름으로 변환한다. diff --git a/src/main/java/chess/domain/piece/PieceType.java b/src/main/java/chess/domain/piece/PieceType.java index e61a1ce622f..23efff2f37a 100644 --- a/src/main/java/chess/domain/piece/PieceType.java +++ b/src/main/java/chess/domain/piece/PieceType.java @@ -1,10 +1,16 @@ package chess.domain.piece; public enum PieceType { - QUEEN, - ROOK, - KNIGHT, - PAWN, - BISHOP, - KING + QUEEN(new Score(9)), + ROOK(new Score(5)), + KNIGHT(new Score(2.5)), + PAWN(new Score(1)), + BISHOP(new Score(3)), + KING(new Score(0)); + + private final Score score; + + PieceType(final Score score) { + this.score = score; + } } diff --git a/src/main/java/chess/domain/piece/Score.java b/src/main/java/chess/domain/piece/Score.java new file mode 100644 index 00000000000..35f045b872d --- /dev/null +++ b/src/main/java/chess/domain/piece/Score.java @@ -0,0 +1,9 @@ +package chess.domain.piece; + +public class Score { + private final double score; + + public Score(final double score) { + this.score = score; + } +} From 9e0f5dd16eb89731eb712c981b7f5aaf12399830 Mon Sep 17 00:00:00 2001 From: jiwon Date: Fri, 24 Mar 2023 11:28:45 +0900 Subject: [PATCH 04/76] =?UTF-8?q?feat:=20=EC=B2=B4=EC=8A=A4=EB=A7=90?= =?UTF-8?q?=EC=9D=B4=20=ED=82=B9=EC=9D=B8=EC=A7=80=20=ED=99=95=EC=9D=B8?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=EC=9D=84=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/domain/piece/Piece.java | 4 ++++ src/test/java/chess/domain/piece/PieceTest.java | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/main/java/chess/domain/piece/Piece.java b/src/main/java/chess/domain/piece/Piece.java index db011c51b7d..3767253f7ad 100644 --- a/src/main/java/chess/domain/piece/Piece.java +++ b/src/main/java/chess/domain/piece/Piece.java @@ -42,6 +42,10 @@ public boolean canAttack(final Position source, final Position target, final boo return movable.canAttack(source, target); } + public boolean isKing() { + return pieceType == PieceType.KING; + } + private boolean validatePawnMove(final Position source, final Position target, final boolean isTargetExist) { if (isPawnFirstMove(source)) { return !isTargetExist; diff --git a/src/test/java/chess/domain/piece/PieceTest.java b/src/test/java/chess/domain/piece/PieceTest.java index d2e86ee0097..93b5daf3ac8 100644 --- a/src/test/java/chess/domain/piece/PieceTest.java +++ b/src/test/java/chess/domain/piece/PieceTest.java @@ -110,4 +110,19 @@ void pawn_canAttack() { assertThat(actual) .isTrue(); } + + @Test + @DisplayName("체스말이 킹인지 판단한다.") + void isKing() { + // given + final Piece king = new Piece(PieceType.KING, CampType.WHITE, new King()); + final Piece pawn = new Piece(PieceType.PAWN, CampType.WHITE, new Pawn()); + + // when, then + assertThat(king.isKing()) + .isTrue(); + + assertThat(pawn.isKing()) + .isFalse(); + } } From 107aaadd2ca52a0e37064bd6c6b0d56534a57da1 Mon Sep 17 00:00:00 2001 From: jiwon Date: Fri, 24 Mar 2023 11:29:13 +0900 Subject: [PATCH 05/76] =?UTF-8?q?feat:=20=ED=98=84=EC=9E=AC=20=EC=B2=B4?= =?UTF-8?q?=EC=8A=A4=ED=8C=90=EC=97=90=20=EC=82=B4=EC=95=84=EC=9E=88?= =?UTF-8?q?=EB=8A=94=20=ED=82=B9=EC=9D=84=20=EC=A1=B0=ED=9A=8C=ED=95=9C?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/chess/domain/board/ChessBoard.java | 9 ++++++++ .../chess/domain/board/ChessBoardTest.java | 21 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/main/java/chess/domain/board/ChessBoard.java b/src/main/java/chess/domain/board/ChessBoard.java index a9b6ccaade9..b96fcbb00c4 100644 --- a/src/main/java/chess/domain/board/ChessBoard.java +++ b/src/main/java/chess/domain/board/ChessBoard.java @@ -4,7 +4,9 @@ import chess.domain.piece.Piece; import chess.domain.piece.move.Position; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; public final class ChessBoard { private final Map board; @@ -45,6 +47,13 @@ public boolean isPossibleRoute(final Position source, final Position target) { return targetPiece == null || !targetPiece.isSameCamp(board.get(source)); } + public List getAliveKings() { + return board.keySet().stream() + .filter(position -> board.get(position).isKing()) + .map(board::get) + .collect(Collectors.toUnmodifiableList()); + } + private boolean isObstructed(final Position target, final Position unitPosition, final Position currentPosition) { if (currentPosition.isSame(target)) { return false; diff --git a/src/test/java/chess/domain/board/ChessBoardTest.java b/src/test/java/chess/domain/board/ChessBoardTest.java index e2fbfa23363..fdfde68c460 100644 --- a/src/test/java/chess/domain/board/ChessBoardTest.java +++ b/src/test/java/chess/domain/board/ChessBoardTest.java @@ -2,6 +2,7 @@ import chess.domain.chess.CampType; import chess.domain.chess.ChessGame; +import chess.domain.piece.King; import chess.domain.piece.Pawn; import chess.domain.piece.Piece; import chess.domain.piece.PieceType; @@ -12,6 +13,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; +import java.util.List; import java.util.Map; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -103,4 +105,23 @@ void isPossibleRoute(final int rank, final int file, final boolean expected) { assertThat(actual) .isSameAs(expected); } + + @Test + @DisplayName("현재 체스판에서 살아있는 킹들을 조회한다.") + void getAliveKings() { + // given + final ChessBoard chessBoard = ChessBoard.getInstance(new ChessGame()); + + // when + List aliveKings = chessBoard.getAliveKings(); + List expected = List.of(new Piece(PieceType.KING, CampType.WHITE, new King()), + new Piece(PieceType.KING, CampType.BLACK, new King())); + + // then + assertThat(aliveKings) + .isEqualTo(expected); + + assertThat(aliveKings.size()) + .isSameAs(2); + } } From e6476e8d2b6cb03d807e53b6b52d597f3e2f2587 Mon Sep 17 00:00:00 2001 From: jiwon Date: Fri, 24 Mar 2023 11:40:41 +0900 Subject: [PATCH 06/76] =?UTF-8?q?feat:=20=ED=98=84=EC=9E=AC=20=EC=B2=B4?= =?UTF-8?q?=EC=8A=A4=20=EA=B2=8C=EC=9E=84=EC=97=90=EC=84=9C=20=ED=82=B9?= =?UTF-8?q?=EC=9D=B4=20=EC=82=B4=EC=95=84=EC=9E=88=EB=8A=94=EC=A7=80=20?= =?UTF-8?q?=ED=8C=90=EB=8B=A8=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +++-- .../java/chess/domain/board/ChessBoardFactory.java | 2 +- src/main/java/chess/domain/chess/ChessGame.java | 8 ++++++++ .../java/chess/domain/chess/ChessGameTest.java | 14 ++++++++++++++ 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 863f585aa26..80ec2b8207e 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,12 @@ - [x] 특정 위치에 존재하는 체스말을 제거한다. - [x] 특정 위치에 체스말을 둔다. - [x] 특정 말의 종류에 따라서 시작 위치에서 종료 위치로 이동 가능한지 판단한다. +- [x] 현재 체스판에서 살아있는 킹들을 조회한다. ### ChessGame - [x] 체스 게임을 진행한다. -- [ ] 현재 차례인 진영이 다른 진영의 킹을 잡았을 때 게임을 종료한다. - - [ ] 현재 차례인 진영이 승리한 진영이 된다. +- [x] 현재 체스 게임에서 킹이 살아있는지 판단한다. ### Score @@ -42,6 +42,7 @@ - [x] 체스말이 입력받은 진영에 속하는지 판단한다. - [x] 체스말이 시작 위치에서 도착 위치로 이동 가능한지 판단한다. - [x] 체스말이 공격 가능한지 판단한다. +- [x] 체스말이 킹인지 판단한다. ### PieceType diff --git a/src/main/java/chess/domain/board/ChessBoardFactory.java b/src/main/java/chess/domain/board/ChessBoardFactory.java index b006ec533dc..a9dc40b073b 100644 --- a/src/main/java/chess/domain/board/ChessBoardFactory.java +++ b/src/main/java/chess/domain/board/ChessBoardFactory.java @@ -38,7 +38,7 @@ static ChessBoardFactory getInstance(final ChessGame chessGame) { return chessBoardFactory; } - public Map createBoard() { + Map createBoard() { final Map board = new HashMap<>(); createWhiteArea(board); createBlackArea(board); diff --git a/src/main/java/chess/domain/chess/ChessGame.java b/src/main/java/chess/domain/chess/ChessGame.java index c325d900d02..6091ab1f8af 100644 --- a/src/main/java/chess/domain/chess/ChessGame.java +++ b/src/main/java/chess/domain/chess/ChessGame.java @@ -4,9 +4,12 @@ import chess.domain.piece.Piece; import chess.domain.piece.move.Position; +import java.util.List; import java.util.Map; public final class ChessGame { + private static final int ALL_KING_ALIVE_COUNT = 2; + private final ChessBoard chessBoard; private CampType currentCamp; @@ -19,6 +22,11 @@ public void setUp(final Position source, final Position target, final CampType c play(source, target); } + public boolean isKingAlive() { + List aliveKings = chessBoard.getAliveKings(); + return aliveKings.size() == ALL_KING_ALIVE_COUNT; + } + private void play(final Position source, final Position target) { validateCamp(source); validateTargetSameCamp(target); diff --git a/src/test/java/chess/domain/chess/ChessGameTest.java b/src/test/java/chess/domain/chess/ChessGameTest.java index 3e82b9f2968..1cf2a9eac51 100644 --- a/src/test/java/chess/domain/chess/ChessGameTest.java +++ b/src/test/java/chess/domain/chess/ChessGameTest.java @@ -1,9 +1,12 @@ package chess.domain.chess; import chess.domain.piece.move.Position; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; class ChessGameTest { @@ -21,4 +24,15 @@ void playMovableFail(final int rank, final int file) { .isInstanceOf(IllegalArgumentException.class) .hasMessage("현재 차례가 아닙니다. 현재 차례 = WHITE"); } + + @Test + @DisplayName("현재 체스 게임에서 킹이 살아있는지 판단한다.") + void isKingAlive() { + // given + final ChessGame chessGame = new ChessGame(); + + // when, then + assertThat(chessGame.isKingAlive()) + .isTrue(); + } } From 2bbad9368da07509031319b66aa826f8532c8d28 Mon Sep 17 00:00:00 2001 From: jiwon Date: Fri, 24 Mar 2023 15:48:39 +0900 Subject: [PATCH 07/76] =?UTF-8?q?feat:=20=EA=B0=81=20=EA=B8=B0=EB=AC=BC?= =?UTF-8?q?=EC=9D=98=20=EC=A0=90=EC=88=98=EC=97=90=20=EB=8C=80=ED=95=B4=20?= =?UTF-8?q?=EB=8D=94=ED=95=98=EA=B3=A0,=20=EB=B9=BC=EA=B3=A0,=20=EA=B3=B1?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=EC=9D=84=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 12 +++-- .../java/chess/domain/piece/PieceType.java | 16 +++--- src/main/java/chess/domain/piece/Score.java | 44 ++++++++++++++- .../java/chess/domain/piece/ScoreTest.java | 54 +++++++++++++++++++ 4 files changed, 116 insertions(+), 10 deletions(-) create mode 100644 src/test/java/chess/domain/piece/ScoreTest.java diff --git a/README.md b/README.md index 80ec2b8207e..37c47116f41 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,9 @@ ### Score - [x] 점수에 대해서 관리한다. +- [x] 인자로 들어온 점수를 합한 값을 반환한다. +- [x] 인자로 들어온 점수를 뺀 값을 반환한다. +- [x] 인자로 들어온 횟수만큼 곱한 값을 반환한다. ### ChessScoreCalculator @@ -48,7 +51,7 @@ - [x] 체스말의 종류를 관리한다. - [x] 특정 체스말이 시작 위치에서 종료 위치까지 이동 가능한지 판단한다. -- [ ] 각 체스말의 점수에 대해 관리한다. +- [x] 각 체스말의 점수에 대해 관리한다. ### Position @@ -128,11 +131,12 @@ - [x] 사용자가 입력한 명령어가 start, move, end인지 검증한다. - [x] 사용자가 입력한 명령어가 start인지 확인한다. - [x] 사용자가 입력한 명령어가 end인지 확인한다. +- [x] 사용자가 입력한 명령어가 status인지 확인한다. - [x] 사용자가 입력한 명령어가 move일 때 올바른 명령어 길이로 들어오는지 확인한다. ### CommandType -- [x] 명령어의 종류에 대해서 관리한다. (start, move, end) +- [x] 명령어의 종류에 대해서 관리한다. (start, move, end, status) ### Status @@ -146,7 +150,9 @@ ### MoveController -- [x] 사용자가 입력한 명령어가 Start라면 예외를 발생시키고, End라면 종료한다. +- [x] 사용자가 입력한 명령어에 따라서 상태를 변경한다. + - [x] 사용자가 입력한 명령어가 Start라면 예외를 발생시키고, End라면 종료한다. + - [x] 사용자가 입력한 status이거나 체스판에 살아있는 킹이 없으면 상태를 status로 변경한다. - [x] 사용자가 입력한 체스말을 시작 지점에서 끝 지점으로 이동시키고, 차례를 변경한다. - [x] 현재 게임이 실행 중인지 판단한다. diff --git a/src/main/java/chess/domain/piece/PieceType.java b/src/main/java/chess/domain/piece/PieceType.java index 23efff2f37a..dab6e4baddb 100644 --- a/src/main/java/chess/domain/piece/PieceType.java +++ b/src/main/java/chess/domain/piece/PieceType.java @@ -1,16 +1,20 @@ package chess.domain.piece; public enum PieceType { - QUEEN(new Score(9)), - ROOK(new Score(5)), - KNIGHT(new Score(2.5)), - PAWN(new Score(1)), - BISHOP(new Score(3)), - KING(new Score(0)); + QUEEN(Score.create(9)), + ROOK(Score.create(5)), + KNIGHT(Score.create(2.5)), + PAWN(Score.create(1)), + BISHOP(Score.create(3)), + KING(Score.create(0)); private final Score score; PieceType(final Score score) { this.score = score; } + + public Score getScore() { + return score; + } } diff --git a/src/main/java/chess/domain/piece/Score.java b/src/main/java/chess/domain/piece/Score.java index 35f045b872d..6a324711bb7 100644 --- a/src/main/java/chess/domain/piece/Score.java +++ b/src/main/java/chess/domain/piece/Score.java @@ -1,9 +1,51 @@ package chess.domain.piece; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + public class Score { + private static final Map CACHE = new HashMap<>(); + private final double score; - public Score(final double score) { + private Score(final double score) { this.score = score; } + + public static Score create(final double score) { + if (!CACHE.containsKey(score)) { + CACHE.put(score, new Score(score)); + } + return CACHE.get(score); + } + + public Score add(final Score other) { + return new Score(score + other.score); + } + + public Score subtract(final Score other) { + return new Score(score - other.score); + } + + public Score multiply(final long count) { + return new Score(score * count); + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final Score score1 = (Score) o; + return Double.compare(score1.score, score) == 0; + } + + @Override + public int hashCode() { + return Objects.hash(score); + } + + public double getScore() { + return score; + } } diff --git a/src/test/java/chess/domain/piece/ScoreTest.java b/src/test/java/chess/domain/piece/ScoreTest.java new file mode 100644 index 00000000000..18781b4fef8 --- /dev/null +++ b/src/test/java/chess/domain/piece/ScoreTest.java @@ -0,0 +1,54 @@ +package chess.domain.piece; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +class ScoreTest { + + @Test + @DisplayName("인자로 들어온 점수를 합한 값을 반환한다.") + void add() { + // given + final Score score = Score.create(1); + final Score expected = Score.create(3.5); + + // when + final Score actual = score.add(Score.create(2.5)); + + // then + assertThat(actual) + .isEqualTo(expected); + } + + @Test + @DisplayName("인자로 들어온 점수를 뺀 값을 반환한다.") + void subtract() { + // given + final Score score = Score.create(3.5); + final Score expected = Score.create(1); + + // when + final Score actual = score.subtract(Score.create(2.5)); + + // then + assertThat(actual) + .isEqualTo(expected); + } + + @Test + @DisplayName("인자로 들어온 횟수만큼 곱한 값을 반환한다.") + void multiply() { + // given + final Score score = Score.create(0.5); + final Score expected = Score.create(1); + + // when + final Score actual = score.multiply(2); + + // then + assertThat(actual) + .isEqualTo(expected); + } +} From 93ea4b9bafaca0ddb636ef1a072dac41153e11d1 Mon Sep 17 00:00:00 2001 From: jiwon Date: Fri, 24 Mar 2023 15:53:54 +0900 Subject: [PATCH 08/76] =?UTF-8?q?feat:=20=EC=B2=B4=EC=8A=A4=EB=A7=90?= =?UTF-8?q?=EC=9D=B4=20=ED=8F=B0=EC=9D=B8=EC=A7=80=20=ED=8C=90=EB=8B=A8?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + src/main/java/chess/domain/piece/Piece.java | 8 ++++++++ src/test/java/chess/domain/piece/PieceTest.java | 15 +++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/README.md b/README.md index 37c47116f41..bb1c5a463a8 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,7 @@ - [x] 체스말이 시작 위치에서 도착 위치로 이동 가능한지 판단한다. - [x] 체스말이 공격 가능한지 판단한다. - [x] 체스말이 킹인지 판단한다. +- [x] 체스말이 폰인지 판단한다. ### PieceType diff --git a/src/main/java/chess/domain/piece/Piece.java b/src/main/java/chess/domain/piece/Piece.java index 3767253f7ad..63f4760f00b 100644 --- a/src/main/java/chess/domain/piece/Piece.java +++ b/src/main/java/chess/domain/piece/Piece.java @@ -46,6 +46,14 @@ public boolean isKing() { return pieceType == PieceType.KING; } + public boolean isPawn() { + return pieceType == PieceType.PAWN; + } + + public Score getScore() { + return pieceType.getScore(); + } + private boolean validatePawnMove(final Position source, final Position target, final boolean isTargetExist) { if (isPawnFirstMove(source)) { return !isTargetExist; diff --git a/src/test/java/chess/domain/piece/PieceTest.java b/src/test/java/chess/domain/piece/PieceTest.java index 93b5daf3ac8..d8561289d42 100644 --- a/src/test/java/chess/domain/piece/PieceTest.java +++ b/src/test/java/chess/domain/piece/PieceTest.java @@ -125,4 +125,19 @@ void isKing() { assertThat(pawn.isKing()) .isFalse(); } + + @Test + @DisplayName("체스말이 폰인지 판단한다.") + void isPawn() { + // given + final Piece king = new Piece(PieceType.KING, CampType.WHITE, new King()); + final Piece pawn = new Piece(PieceType.PAWN, CampType.WHITE, new Pawn()); + + // when, then + assertThat(pawn.isPawn()) + .isTrue(); + + assertThat(king.isPawn()) + .isFalse(); + } } From 29208745660b426505c168b74a44c3bdc286332c Mon Sep 17 00:00:00 2001 From: jiwon Date: Fri, 24 Mar 2023 16:01:26 +0900 Subject: [PATCH 09/76] =?UTF-8?q?feat:=20=ED=9D=91=EC=A7=84=EC=98=81,=20?= =?UTF-8?q?=EB=B0=B1=EC=A7=84=EC=98=81=EC=9D=98=20=EC=B2=B4=EC=8A=A4?= =?UTF-8?q?=ED=8C=90=EC=9D=84=20=EB=B0=98=ED=99=98=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 ++ .../java/chess/domain/board/ChessBoard.java | 9 +++++- .../java/chess/domain/chess/ChessGame.java | 8 +++++ .../chess/domain/board/ChessBoardTest.java | 17 ++++++++++ .../chess/domain/chess/ChessGameTest.java | 31 +++++++++++++++++++ 5 files changed, 67 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bb1c5a463a8..e7ab9f2d350 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,14 @@ - [x] 특정 위치에 체스말을 둔다. - [x] 특정 말의 종류에 따라서 시작 위치에서 종료 위치로 이동 가능한지 판단한다. - [x] 현재 체스판에서 살아있는 킹들을 조회한다. +- [x] 입력받은 진영의 체스판을 반환한다. ### ChessGame - [x] 체스 게임을 진행한다. - [x] 현재 체스 게임에서 킹이 살아있는지 판단한다. +- [x] WHITE 진영의 체스판을 반환한다. +- [x] BLACK 진영의 체스판을 반환한다. ### Score diff --git a/src/main/java/chess/domain/board/ChessBoard.java b/src/main/java/chess/domain/board/ChessBoard.java index b96fcbb00c4..05607dfbebb 100644 --- a/src/main/java/chess/domain/board/ChessBoard.java +++ b/src/main/java/chess/domain/board/ChessBoard.java @@ -1,5 +1,6 @@ package chess.domain.board; +import chess.domain.chess.CampType; import chess.domain.chess.ChessGame; import chess.domain.piece.Piece; import chess.domain.piece.move.Position; @@ -49,11 +50,17 @@ public boolean isPossibleRoute(final Position source, final Position target) { public List getAliveKings() { return board.keySet().stream() - .filter(position -> board.get(position).isKing()) .map(board::get) + .filter(Piece::isKing) .collect(Collectors.toUnmodifiableList()); } + public Map getBoardByCamp(final CampType campType) { + return board.entrySet().stream() + .filter(entry -> entry.getValue().isSameCamp(campType)) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + private boolean isObstructed(final Position target, final Position unitPosition, final Position currentPosition) { if (currentPosition.isSame(target)) { return false; diff --git a/src/main/java/chess/domain/chess/ChessGame.java b/src/main/java/chess/domain/chess/ChessGame.java index 6091ab1f8af..4d30f148f4c 100644 --- a/src/main/java/chess/domain/chess/ChessGame.java +++ b/src/main/java/chess/domain/chess/ChessGame.java @@ -27,6 +27,14 @@ public boolean isKingAlive() { return aliveKings.size() == ALL_KING_ALIVE_COUNT; } + public Map getWhiteBoard() { + return chessBoard.getBoardByCamp(CampType.WHITE); + } + + public Map getBlackBoard() { + return chessBoard.getBoardByCamp(CampType.BLACK); + } + private void play(final Position source, final Position target) { validateCamp(source); validateTargetSameCamp(target); diff --git a/src/test/java/chess/domain/board/ChessBoardTest.java b/src/test/java/chess/domain/board/ChessBoardTest.java index fdfde68c460..fb49559fddd 100644 --- a/src/test/java/chess/domain/board/ChessBoardTest.java +++ b/src/test/java/chess/domain/board/ChessBoardTest.java @@ -124,4 +124,21 @@ void getAliveKings() { assertThat(aliveKings.size()) .isSameAs(2); } + + @Test + @DisplayName("입력받은 진영의 체스판을 반환한다.") + void getBoardByCamp() { + // given + final ChessBoard chessBoard = ChessBoard.getInstance(new ChessGame()); + + // when + final Map whiteBoard = chessBoard.getBoardByCamp(CampType.WHITE); + final Map blackBoard = chessBoard.getBoardByCamp(CampType.BLACK); + + // then + assertThat(whiteBoard.size()) + .isEqualTo(16); + assertThat(blackBoard.size()) + .isEqualTo(16); + } } diff --git a/src/test/java/chess/domain/chess/ChessGameTest.java b/src/test/java/chess/domain/chess/ChessGameTest.java index 1cf2a9eac51..ea2c0eb6a0e 100644 --- a/src/test/java/chess/domain/chess/ChessGameTest.java +++ b/src/test/java/chess/domain/chess/ChessGameTest.java @@ -1,11 +1,14 @@ package chess.domain.chess; +import chess.domain.piece.Piece; import chess.domain.piece.move.Position; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; +import java.util.Map; + import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; @@ -35,4 +38,32 @@ void isKingAlive() { assertThat(chessGame.isKingAlive()) .isTrue(); } + + @Test + @DisplayName("WHITE 진영의 체스판을 반환한다.") + void getWhiteBoard() { + // given + final ChessGame chessGame = new ChessGame(); + + // when + final Map whiteBoard = chessGame.getWhiteBoard(); + + // then + assertThat(whiteBoard.size()) + .isEqualTo(16); + } + + @Test + @DisplayName("BLACK 진영의 체스판을 반환한다.") + void getBlackBoard() { + // given + final ChessGame chessGame = new ChessGame(); + + // when + final Map blackBoard = chessGame.getBlackBoard(); + + // then + assertThat(blackBoard.size()) + .isEqualTo(16); + } } From 04e99207616d5a0c23a0fe6fce6307ee48bbf4e6 Mon Sep 17 00:00:00 2001 From: jiwon Date: Fri, 24 Mar 2023 17:05:41 +0900 Subject: [PATCH 10/76] =?UTF-8?q?feat:=20=ED=8F=B0=EC=9D=B4=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=EC=9D=B4=EB=82=98=20=EA=B3=B5=EA=B2=A9=ED=95=A0=20?= =?UTF-8?q?=EB=95=8C=20=EC=95=9E=EC=9C=BC=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= =?UTF-8?q?=ED=95=98=EB=8A=94=EC=A7=80=20=EA=B2=80=EC=A6=9D=ED=95=9C?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/domain/piece/Piece.java | 19 ++++++++++-- .../java/chess/domain/piece/PieceTest.java | 29 +++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/main/java/chess/domain/piece/Piece.java b/src/main/java/chess/domain/piece/Piece.java index 63f4760f00b..15755d6e3f5 100644 --- a/src/main/java/chess/domain/piece/Piece.java +++ b/src/main/java/chess/domain/piece/Piece.java @@ -30,14 +30,16 @@ public boolean isSameCamp(final CampType diffType) { public boolean canMove(final Position source, final Position target, final boolean isTargetExist) { if (pieceType == PieceType.PAWN && movable.canMove(source, target)) { + validatePawnDirection(source, target); return validatePawnMove(source, target, isTargetExist); } return movable.canMove(source, target); } public boolean canAttack(final Position source, final Position target, final boolean isTargetExist) { - if (pieceType == PieceType.PAWN && movable.canAttack(source, target) && !isTargetExist) { - throw new IllegalArgumentException("폰이 공격할 수 있는 위치가 아닙니다."); + if (pieceType == PieceType.PAWN) { + validatePawnDirection(source, target); + validatePawnCanAttack(source, target, isTargetExist); } return movable.canAttack(source, target); } @@ -73,6 +75,19 @@ private boolean validatePawnOneMove(final Position source, final Position target return !isTargetExist; } + private void validatePawnDirection(final Position source, final Position target) { + if ((campType == CampType.WHITE && source.isRankGreaterThan(target)) || + (campType == CampType.BLACK && target.isRankGreaterThan(source))) { + throw new IllegalArgumentException("폰은 앞으로만 이동할 수 있습니다."); + } + } + + private void validatePawnCanAttack(final Position source, final Position target, final boolean isTargetExist) { + if (movable.canAttack(source, target) && !isTargetExist) { + throw new IllegalArgumentException("폰이 공격할 수 있는 위치가 아닙니다."); + } + } + @Override public boolean equals(final Object o) { if (this == o) return true; diff --git a/src/test/java/chess/domain/piece/PieceTest.java b/src/test/java/chess/domain/piece/PieceTest.java index d8561289d42..9147d35ea20 100644 --- a/src/test/java/chess/domain/piece/PieceTest.java +++ b/src/test/java/chess/domain/piece/PieceTest.java @@ -81,6 +81,20 @@ void pawn_canMoveFail() { .hasMessage("폰은 처음 이후 1칸만 전진할 수 있습니다."); } + @ParameterizedTest(name = "폰은 앞으로만 이동할 수 있다.") + @CsvSource(value = {"1:WHITE", "3:BLACK"}, delimiter = ':') + void pawn_canMoveFail(final int rank, final CampType currentCamp) { + // given + final Piece pawn = new Piece(PieceType.PAWN, currentCamp, new Pawn()); + final Position source = new Position(2, 1); + final Position target = new Position(rank, 1); + + // when, then + assertThatThrownBy(() -> pawn.canMove(source, target, false)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("폰은 앞으로만 이동할 수 있습니다."); + } + @Test @DisplayName("폰은 공격 가능한 위치에 상대 기물이 존재하지 않는 경우 예외가 발생한다.") void pawn_canAttackFail() { @@ -95,6 +109,7 @@ void pawn_canAttackFail() { .hasMessage("폰이 공격할 수 있는 위치가 아닙니다."); } + @Test @DisplayName("폰은 공격 가능한 위치에 상대 기물이 존재하는 경우 공격할 수 있다.") void pawn_canAttack() { @@ -111,6 +126,20 @@ void pawn_canAttack() { .isTrue(); } + @ParameterizedTest(name = "폰은 앞에 있는 기물만 공격할 수 있다.") + @CsvSource(value = {"1:0:WHITE", "3:2:BLACK"}, delimiter = ':') + void pawn_canAttackFail(final int rank, final int file, final CampType currentCamp) { + // given + final Piece pawn = new Piece(PieceType.PAWN, currentCamp, new Pawn()); + final Position source = new Position(2, 1); + final Position target = new Position(rank, file); + + // when, then + assertThatThrownBy(() -> pawn.canMove(source, target, false)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("폰은 앞으로만 이동할 수 있습니다."); + } + @Test @DisplayName("체스말이 킹인지 판단한다.") void isKing() { From bb61e7642f2f1f708e5604acf92e3b062fe6dcc5 Mon Sep 17 00:00:00 2001 From: jiwon Date: Sat, 25 Mar 2023 11:36:00 +0900 Subject: [PATCH 11/76] =?UTF-8?q?feat:=20=ED=98=84=EC=9E=AC=20=EC=B2=B4?= =?UTF-8?q?=EC=8A=A4=ED=8C=90=EC=9D=98=20=EA=B0=81=20=EC=A7=84=EC=98=81?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=A0=90=EC=88=98=EB=A5=BC=20?= =?UTF-8?q?=EA=B3=84=EC=82=B0=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +- .../domain/chess/ChessGameCalculator.java | 62 +++++++++++++++++++ .../java/chess/domain/chess/vo/ScoreVO.java | 36 +++++++++++ .../domain/chess/ChessGameCalculatorTest.java | 26 ++++++++ 4 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 src/main/java/chess/domain/chess/ChessGameCalculator.java create mode 100644 src/main/java/chess/domain/chess/vo/ScoreVO.java create mode 100644 src/test/java/chess/domain/chess/ChessGameCalculatorTest.java diff --git a/README.md b/README.md index e7ab9f2d350..d3b112c50e1 100644 --- a/README.md +++ b/README.md @@ -32,8 +32,7 @@ ### ChessScoreCalculator -- [ ] 체스 게임의 점수에 대해서 계산한다. -- [ ] 같은 세로줄에 같은 진영의 폰이 있는지 확인한다. +- [x] 현재 체스판의 각 진영에 대한 점수를 계산한다. ### CampType diff --git a/src/main/java/chess/domain/chess/ChessGameCalculator.java b/src/main/java/chess/domain/chess/ChessGameCalculator.java new file mode 100644 index 00000000000..b02bdf6c1d9 --- /dev/null +++ b/src/main/java/chess/domain/chess/ChessGameCalculator.java @@ -0,0 +1,62 @@ +package chess.domain.chess; + +import chess.domain.chess.vo.ScoreVO; +import chess.domain.piece.Piece; +import chess.domain.piece.Score; +import chess.domain.piece.move.Position; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public final class ChessGameCalculator { + + private static final Score DEFAULT_SCORE = Score.create(0); + private static final int PAWN_SUBTRACT_COUNT_THRESHOLD = 1; + private static final Score PAWN_SPECIAL_SCORE = Score.create(0.5); + + public static ScoreVO calculate(final ChessGame chessGame) { + final Map whiteBoard = chessGame.getWhiteBoard(); + Score whiteScore = calculateScore(whiteBoard); + + final Map blackBoard = chessGame.getBlackBoard(); + Score blackScore = calculateScore(blackBoard); + + return new ScoreVO(whiteScore, blackScore); + } + + private static Score calculateScore(Map board) { + final Map> piecesByFile = groupBoardByFile(board); + Score score = calculateTotalScore(board); + for (List pieces : piecesByFile.values()) { + final Score subtractScore = getSubtractScoreByPawn(pieces); + score = score.subtract(subtractScore); + } + return score; + } + + private static Score calculateTotalScore(Map board) { + return board.values().stream() + .map(Piece::getScore) + .reduce(DEFAULT_SCORE, Score::add); + } + + private static Map> groupBoardByFile(final Map board) { + return board.entrySet().stream() + .collect(Collectors.groupingBy(entry -> entry.getKey().getFile(), + Collectors.mapping(Map.Entry::getValue, Collectors.toList()) + )); + } + + private static Score getSubtractScoreByPawn(final List pieces) { + final long pawnCount = getPawnCount(pieces); + if (pawnCount > PAWN_SUBTRACT_COUNT_THRESHOLD) { + return PAWN_SPECIAL_SCORE.multiply(pawnCount); + } + return DEFAULT_SCORE; + } + + private static long getPawnCount(final List pieces) { + return pieces.stream().filter(Piece::isPawn).count(); + } +} diff --git a/src/main/java/chess/domain/chess/vo/ScoreVO.java b/src/main/java/chess/domain/chess/vo/ScoreVO.java new file mode 100644 index 00000000000..424eccc9fcf --- /dev/null +++ b/src/main/java/chess/domain/chess/vo/ScoreVO.java @@ -0,0 +1,36 @@ +package chess.domain.chess.vo; + +import chess.domain.piece.Score; + +import java.util.Objects; + +public class ScoreVO { + private final Score whiteScore; + private final Score blackScore; + + public ScoreVO(final Score whiteScore, final Score blackScore) { + this.whiteScore = whiteScore; + this.blackScore = blackScore; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final ScoreVO scoreVO = (ScoreVO) o; + return Objects.equals(whiteScore, scoreVO.whiteScore) && Objects.equals(blackScore, scoreVO.blackScore); + } + + @Override + public int hashCode() { + return Objects.hash(whiteScore, blackScore); + } + + public Score getWhiteScore() { + return whiteScore; + } + + public Score getBlackScore() { + return blackScore; + } +} diff --git a/src/test/java/chess/domain/chess/ChessGameCalculatorTest.java b/src/test/java/chess/domain/chess/ChessGameCalculatorTest.java new file mode 100644 index 00000000000..949d2da9ea0 --- /dev/null +++ b/src/test/java/chess/domain/chess/ChessGameCalculatorTest.java @@ -0,0 +1,26 @@ +package chess.domain.chess; + +import chess.domain.chess.vo.ScoreVO; +import chess.domain.piece.Score; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +class ChessGameCalculatorTest { + + @Test + @DisplayName("현재 체스판의 각 진영에 대한 점수를 계산한다.") + void calculate() { + // given + final ChessGame chessGame = new ChessGame(); + final ScoreVO expected = new ScoreVO(Score.create(38.0), Score.create(38.0)); + + // when + ScoreVO actual = ChessGameCalculator.calculate(chessGame); + + // then + assertThat(actual) + .isEqualTo(expected); + } +} From a15f708d2de85d99e5ac67d3de46e5eb743d3390 Mon Sep 17 00:00:00 2001 From: jiwon Date: Sat, 25 Mar 2023 11:37:10 +0900 Subject: [PATCH 12/76] =?UTF-8?q?feat:=20status=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=EB=AA=85=EB=A0=B9=EC=96=B4=EC=99=80=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EB=A5=BC=20=EC=B6=94=EA=B0=80=ED=95=9C?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/controller/Command.java | 20 +++- .../java/chess/controller/CommandType.java | 2 +- .../java/chess/controller/CommandTest.java | 102 ++++++++++++++++++ 3 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 src/test/java/chess/controller/CommandTest.java diff --git a/src/main/java/chess/controller/Command.java b/src/main/java/chess/controller/Command.java index c88af463d12..16e70c78159 100644 --- a/src/main/java/chess/controller/Command.java +++ b/src/main/java/chess/controller/Command.java @@ -2,6 +2,7 @@ import java.util.Arrays; import java.util.List; +import java.util.Objects; public final class Command { private static final int COMMAND_INDEX = 0; @@ -36,8 +37,25 @@ public boolean isEnd() { return type == CommandType.END; } + public boolean isStatus() { + return type == CommandType.STATUS; + } + public boolean isCorrectWhenMove() { - return commands.size() == MOVE_COMMAND_SIZE; + return type == CommandType.MOVE && commands.size() == MOVE_COMMAND_SIZE; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final Command command = (Command) o; + return type == command.type && Objects.equals(commands, command.commands); + } + + @Override + public int hashCode() { + return Objects.hash(type, commands); } public List getCommands() { diff --git a/src/main/java/chess/controller/CommandType.java b/src/main/java/chess/controller/CommandType.java index a5eb3e6d2d8..92cc334da17 100644 --- a/src/main/java/chess/controller/CommandType.java +++ b/src/main/java/chess/controller/CommandType.java @@ -1,5 +1,5 @@ package chess.controller; public enum CommandType { - START, MOVE, END + START, MOVE, END, STATUS } diff --git a/src/test/java/chess/controller/CommandTest.java b/src/test/java/chess/controller/CommandTest.java new file mode 100644 index 00000000000..82148ba3e32 --- /dev/null +++ b/src/test/java/chess/controller/CommandTest.java @@ -0,0 +1,102 @@ +package chess.controller; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + +class CommandTest { + + @ParameterizedTest(name = "입력한 명령어에 따라서 Command를 조회해온다.") + @CsvSource(value = {"start:START", "move a2 a4:MOVE", "end:END", "status:STATUS"}, delimiter = ':') + void findCommand_success(final String command, final CommandType commandType) { + // given + final List commands = Arrays.asList(command.split(" ")); + final Command expected = new Command(commandType, commands); + + // when + final Command actual = Command.findCommand(commands); + + // then + assertThat(actual) + .isEqualTo(expected); + } + + @ParameterizedTest(name = "start, move, end, status 외의 명령어를 입력하면 예외가 발생한다.") + @ValueSource(strings = {"star", "@#$F@#", "203948029f"}) + void findCommand_fail(final String command) { + // given + final List commands = Arrays.asList(command.split(" ")); + + // when, then + assertThatThrownBy(() -> Command.findCommand(commands)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("잘못된 명령어 입력입니다."); + } + + @Test + @DisplayName("현재 명령어가 start인지 판단한다.") + void isStart() { + // given + final Command command = new Command(CommandType.START, List.of("start")); + + // when, then + assertThat(command.isStart()) + .isTrue(); + } + + @Test + @DisplayName("현재 명령어가 move인지 판단한다.") + void isMove() { + // given + final Command command = new Command(CommandType.MOVE, List.of("move", "a2", "a4")); + + // when, then + assertThat(command.isMove()) + .isTrue(); + } + + @Test + @DisplayName("현재 명령어가 end인지 판단한다.") + void isEnd() { + // given + final Command command = new Command(CommandType.END, List.of("end")); + + // when, then + assertThat(command.isEnd()) + .isTrue(); + } + + @Test + @DisplayName("현재 명령어가 status인지 판단한다.") + void isStatus() { + // given + final Command command = new Command(CommandType.STATUS, List.of("status")); + + // when, then + assertThat(command.isStatus()) + .isTrue(); + } + + @ParameterizedTest(name = "사용자가 입력한 명령어가 move일 때 명령어의 길이가 3인지 판단한다.") + @CsvSource(value = {"move:false", "move : false", "move a3:false", "move a2 a4:true", "move a3 a4 a5:false"}, delimiter = ':') + void isCorrectWhenMove(final String userCommand, final boolean expected) { + // given + List commands = Arrays.asList(userCommand.split(" ")); + final Command command = new Command(CommandType.MOVE, commands); + + // when + boolean actual = command.isCorrectWhenMove(); + + // then + assertThat(actual) + .isSameAs(expected); + } +} From c183445ca2a29986c1ccb130463b5d4742820aa8 Mon Sep 17 00:00:00 2001 From: jiwon Date: Sat, 25 Mar 2023 13:02:34 +0900 Subject: [PATCH 13/76] =?UTF-8?q?feat:=20=EA=B0=81=20=EC=A7=84=EC=98=81?= =?UTF-8?q?=EC=9D=98=20=EC=A0=90=EC=88=98=EC=99=80=20=EC=9D=B4=EA=B8=B4=20?= =?UTF-8?q?=EC=A7=84=EC=98=81=EC=97=90=20=EB=8C=80=ED=95=B4=EC=84=9C=20?= =?UTF-8?q?=EC=B6=9C=EB=A0=A5=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + .../chess/controller/dto/ChessResultDto.java | 19 +++++++++++++ .../mapper/ChessResultDtoMapper.java | 10 +++++++ src/main/java/chess/view/OutputView.java | 27 +++++++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 src/main/java/chess/controller/dto/ChessResultDto.java create mode 100644 src/main/java/chess/controller/mapper/ChessResultDtoMapper.java diff --git a/README.md b/README.md index d3b112c50e1..3525fa81b69 100644 --- a/README.md +++ b/README.md @@ -177,6 +177,7 @@ - [x] 게임 안내 메시지를 출력한다. - [x] 체스판에 있는 체스말을 출력하고, 비어있는 곳은 .으로 출력한다. - source에 있는 말이 target으로 이동된 체스판을 출력한다. +- [x] 각 진영의 점수와 이긴 진영에 대해서 출력한다. --- diff --git a/src/main/java/chess/controller/dto/ChessResultDto.java b/src/main/java/chess/controller/dto/ChessResultDto.java new file mode 100644 index 00000000000..c98e69f2973 --- /dev/null +++ b/src/main/java/chess/controller/dto/ChessResultDto.java @@ -0,0 +1,19 @@ +package chess.controller.dto; + +public class ChessResultDto { + private final double whiteScore; + private final double blackScore; + + public ChessResultDto(final double whiteScore, final double blackScore) { + this.whiteScore = whiteScore; + this.blackScore = blackScore; + } + + public double getWhiteScore() { + return whiteScore; + } + + public double getBlackScore() { + return blackScore; + } +} diff --git a/src/main/java/chess/controller/mapper/ChessResultDtoMapper.java b/src/main/java/chess/controller/mapper/ChessResultDtoMapper.java new file mode 100644 index 00000000000..2c8383bbdd8 --- /dev/null +++ b/src/main/java/chess/controller/mapper/ChessResultDtoMapper.java @@ -0,0 +1,10 @@ +package chess.controller.mapper; + +import chess.controller.dto.ChessResultDto; +import chess.domain.chess.vo.ScoreVO; + +public class ChessResultDtoMapper { + public static ChessResultDto from(final ScoreVO scoreVO) { + return new ChessResultDto(scoreVO.getWhiteScore().getScore(), scoreVO.getBlackScore().getScore()); + } +} diff --git a/src/main/java/chess/view/OutputView.java b/src/main/java/chess/view/OutputView.java index dd7ca613ac3..ffa9af36838 100644 --- a/src/main/java/chess/view/OutputView.java +++ b/src/main/java/chess/view/OutputView.java @@ -1,6 +1,7 @@ package chess.view; import chess.controller.dto.ChessBoardDto; +import chess.controller.dto.ChessResultDto; import chess.controller.dto.PieceDto; import chess.controller.dto.PositionDto; @@ -17,6 +18,15 @@ public final class OutputView { "> 게임 시작 : %s\n" + "> 게임 종료 : %s\n" + "> 게임 이동 : %s source위치 target위치 - 예. move b2 b3"; + private static final String RESULT_MESSAGE = "> 체스 게임 결과입니다.\n" + + "> 백진영 (WHITE) : %.1f\n" + + "> 흑진영 (BLACK) : %.1f\n" + + "> 승리한 팀 : %s\n"; + + private static final String DRAW = "DRAW!"; + private static final String WHITE = "WHITE"; + private static final String BLACK = "BLACK"; + public static void print(final String message) { System.out.println(message); @@ -35,6 +45,13 @@ public static void printBoard(final ChessBoardDto chessBoardDto) { print(boardMessage.toString()); } + public static void printChessResult(final ChessResultDto chessResultDto) { + final double whiteScore = chessResultDto.getWhiteScore(); + final double blackScore = chessResultDto.getBlackScore(); + final String winnerCamp = getWinnerCamp(whiteScore, blackScore); + print(String.format(RESULT_MESSAGE, whiteScore, blackScore, winnerCamp)); + } + private static String makeFileMessage(final ChessBoardDto chessBoardDto, final int rank) { final StringBuilder fileMessage = new StringBuilder(); for (int file = 0; file < BOARD_SIZE; file++) { @@ -51,4 +68,14 @@ private static char getPieceName(final ChessBoardDto chessBoardDto, final int ra } return BLANK; } + + private static String getWinnerCamp(final double whiteScore, final double blackScore) { + if (whiteScore == blackScore) { + return DRAW; + } + if (whiteScore < blackScore) { + return BLACK; + } + return WHITE; + } } From 54ff520ceded4b8b3a0f1e4e23b6be1fbca91f96 Mon Sep 17 00:00:00 2001 From: jiwon Date: Sat, 25 Mar 2023 14:09:18 +0900 Subject: [PATCH 14/76] =?UTF-8?q?feat:=20=ED=82=B9=EC=9D=B4=20=EC=82=AC?= =?UTF-8?q?=EB=A7=9D=ED=95=98=EC=98=80=EB=8B=A4=EB=A9=B4=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=EC=9D=98=20=EC=A7=84=ED=96=89=20=EC=83=81=ED=83=9C?= =?UTF-8?q?=EB=A5=BC=20false=EB=A1=9C=20=EB=A7=8C=EB=93=A0=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/chess/domain/chess/ChessGame.java | 17 ++++++------- .../chess/domain/chess/ChessGameHelper.java | 24 +++++++++++++++++++ .../chess/domain/chess/ChessGameTest.java | 18 +++++++++----- 3 files changed, 45 insertions(+), 14 deletions(-) create mode 100644 src/test/java/chess/domain/chess/ChessGameHelper.java diff --git a/src/main/java/chess/domain/chess/ChessGame.java b/src/main/java/chess/domain/chess/ChessGame.java index 4d30f148f4c..5e787e6d530 100644 --- a/src/main/java/chess/domain/chess/ChessGame.java +++ b/src/main/java/chess/domain/chess/ChessGame.java @@ -17,14 +17,9 @@ public ChessGame() { this.chessBoard = ChessBoard.getInstance(this); } - public void setUp(final Position source, final Position target, final CampType currentCamp) { + public boolean run(final Position source, final Position target, final CampType currentCamp) { this.currentCamp = currentCamp; - play(source, target); - } - - public boolean isKingAlive() { - List aliveKings = chessBoard.getAliveKings(); - return aliveKings.size() == ALL_KING_ALIVE_COUNT; + return play(source, target); } public Map getWhiteBoard() { @@ -35,7 +30,7 @@ public Map getBlackBoard() { return chessBoard.getBoardByCamp(CampType.BLACK); } - private void play(final Position source, final Position target) { + private boolean play(final Position source, final Position target) { validateCamp(source); validateTargetSameCamp(target); validateObstacle(source, target); @@ -43,6 +38,7 @@ private void play(final Position source, final Position target) { throw new IllegalArgumentException("이동할 수 없는 위치입니다."); } movePiece(source, target); + return isKingAlive(); } private void validateObstacle(final Position source, final Position target) { @@ -94,6 +90,11 @@ private void validatePieceExistence(final Position position) { } } + private boolean isKingAlive() { + List aliveKings = chessBoard.getAliveKings(); + return aliveKings.size() == ALL_KING_ALIVE_COUNT; + } + public Map getChessBoard() { return chessBoard.getBoard(); } diff --git a/src/test/java/chess/domain/chess/ChessGameHelper.java b/src/test/java/chess/domain/chess/ChessGameHelper.java new file mode 100644 index 00000000000..bc04c023147 --- /dev/null +++ b/src/test/java/chess/domain/chess/ChessGameHelper.java @@ -0,0 +1,24 @@ +package chess.domain.chess; + +import chess.domain.piece.move.Position; + +public class ChessGameHelper { + public static boolean playKingDie(final ChessGame chessGame) { + chessGame.run(new Position(7, 1), new Position(5, 0), CampType.BLACK); + chessGame.run(new Position(3, 0), new Position(4, 0), CampType.WHITE); + chessGame.run(new Position(6, 1), new Position(5, 1), CampType.BLACK); + chessGame.run(new Position(4, 0), new Position(5, 1), CampType.WHITE); + chessGame.run(new Position(6, 2), new Position(5, 2), CampType.BLACK); + chessGame.run(new Position(0, 0), new Position(5, 0), CampType.WHITE); + chessGame.run(new Position(5, 2), new Position(4, 2), CampType.BLACK); + chessGame.run(new Position(1, 3), new Position(3, 3), CampType.WHITE); + chessGame.run(new Position(6, 4), new Position(4, 4), CampType.BLACK); + chessGame.run(new Position(0, 2), new Position(5, 7), CampType.WHITE); + chessGame.run(new Position(7, 3), new Position(3, 7), CampType.BLACK); + chessGame.run(new Position(0, 6), new Position(2, 5), CampType.WHITE); + chessGame.run(new Position(7, 4), new Position(6, 4), CampType.BLACK); + chessGame.run(new Position(3, 3), new Position(4, 3), CampType.WHITE); + chessGame.run(new Position(6, 4), new Position(5, 4), CampType.BLACK); + return chessGame.run(new Position(4, 3), new Position(5, 4), CampType.WHITE); + } +} diff --git a/src/test/java/chess/domain/chess/ChessGameTest.java b/src/test/java/chess/domain/chess/ChessGameTest.java index ea2c0eb6a0e..0148c5eccdd 100644 --- a/src/test/java/chess/domain/chess/ChessGameTest.java +++ b/src/test/java/chess/domain/chess/ChessGameTest.java @@ -23,20 +23,26 @@ void playMovableFail(final int rank, final int file) { final Position target = new Position(6, 7); // when, then - assertThatThrownBy(() -> chessGame.setUp(source, target, CampType.WHITE)) + assertThatThrownBy(() -> chessGame.run(source, target, CampType.WHITE)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("현재 차례가 아닙니다. 현재 차례 = WHITE"); } @Test - @DisplayName("현재 체스 게임에서 킹이 살아있는지 판단한다.") - void isKingAlive() { + @DisplayName("모든 진영의 왕이 살아있는 것이 아니라면 false를 반환한다.") + void run() { // given final ChessGame chessGame = new ChessGame(); + final Position source = new Position(1, 0); + final Position target = new Position(3, 0); - // when, then - assertThat(chessGame.isKingAlive()) - .isTrue(); + // when + chessGame.run(source, target, CampType.WHITE); + boolean isGameRun = ChessGameHelper.playKingDie(chessGame); + + // then + assertThat(isGameRun) + .isFalse(); } @Test From 47be1dc9b9ee0adbb4eac4c7c17a9b77fe63d14b Mon Sep 17 00:00:00 2001 From: jiwon Date: Sat, 25 Mar 2023 14:09:50 +0900 Subject: [PATCH 15/76] =?UTF-8?q?feat:=20=EA=B2=8C=EC=9E=84=EC=9D=B4=20?= =?UTF-8?q?=EC=8B=9C=EC=9E=91=20=EC=83=81=ED=83=9C=EC=9D=BC=20=EB=95=8C=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=EA=B0=80=20=EC=9E=85=EB=A0=A5?= =?UTF-8?q?=ED=95=9C=20=EB=AA=85=EB=A0=B9=EC=96=B4=EA=B0=80=20status?= =?UTF-8?q?=EB=A9=B4=20=EC=98=88=EC=99=B8=EA=B0=80=20=EB=B0=9C=EC=83=9D?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/status/StartController.java | 2 +- .../controller/status/StartControllerTest.java | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main/java/chess/controller/status/StartController.java b/src/main/java/chess/controller/status/StartController.java index de300e5432b..fde519d19d7 100644 --- a/src/main/java/chess/controller/status/StartController.java +++ b/src/main/java/chess/controller/status/StartController.java @@ -17,7 +17,7 @@ public Controller checkCommand(final Command command, final Runnable runnable) { if (command.isEnd()) { return new EndController(); } - if (command.isMove()) { + if (!command.isStart()) { throw new IllegalArgumentException("게임이 시작되지 않았습니다."); } runnable.run(); diff --git a/src/test/java/chess/controller/status/StartControllerTest.java b/src/test/java/chess/controller/status/StartControllerTest.java index 0391e1b1f6c..8a22926f762 100644 --- a/src/test/java/chess/controller/status/StartControllerTest.java +++ b/src/test/java/chess/controller/status/StartControllerTest.java @@ -13,9 +13,8 @@ class StartControllerTest { - @Test @DisplayName(value = "게임이 시작 상태일 때 사용자가 입력한 명령어가 move면 예외가 발생한다.") - void checkCommandFailWhenMove() { + void checkCommandMove() { // given final StartController startController = new StartController(new ChessGame()); final Command command = new Command(CommandType.MOVE, List.of("move a2")); @@ -27,9 +26,22 @@ void checkCommandFailWhenMove() { .hasMessage("게임이 시작되지 않았습니다."); } + @DisplayName(value = "게임이 시작 상태일 때 사용자가 입력한 명령어가 status면 예외가 발생한다.") + void checkCommandStatus() { + // given + final StartController startController = new StartController(new ChessGame()); + final Command command = new Command(CommandType.STATUS, List.of("status")); + + // when, then + assertThatThrownBy(() -> startController.checkCommand(command, () -> { + })) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("게임이 시작되지 않았습니다."); + } + @Test @DisplayName(value = "게임이 시작 상태일 때 사용자가 입력한 명령어가 end면 게임이 종료된다.") - void checkCommand() { + void checkCommandEnd() { // given final StartController startController = new StartController(new ChessGame()); final Command command = new Command(CommandType.END, List.of("end")); From 75079e70032771715e9101a68050f9a4b4b2d065 Mon Sep 17 00:00:00 2001 From: jiwon Date: Sat, 25 Mar 2023 14:10:20 +0900 Subject: [PATCH 16/76] =?UTF-8?q?feat:=20EndController=EC=9D=98=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9E=90=EC=97=90=20=EB=8C=80=ED=95=B4=20?= =?UTF-8?q?=EC=A0=91=EA=B7=BC=20=EC=A0=9C=EC=96=B4=EC=9E=90=EB=A5=BC=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/controller/ChessHandler.java | 2 +- src/main/java/chess/controller/status/EndController.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/chess/controller/ChessHandler.java b/src/main/java/chess/controller/ChessHandler.java index 07d7a7324d5..7ac4c407eb6 100644 --- a/src/main/java/chess/controller/ChessHandler.java +++ b/src/main/java/chess/controller/ChessHandler.java @@ -26,7 +26,7 @@ private void start(final ChessGame chessGame) { private Controller play(final ChessGame chessGame, Controller controller) { try { - List commands = InputView.getCommand(); + final List commands = InputView.getCommand(); final Command command = Command.findCommand(commands); controller = controller.checkCommand(command, () -> OutputView.printBoard( diff --git a/src/main/java/chess/controller/status/EndController.java b/src/main/java/chess/controller/status/EndController.java index 20c52655d8a..b9895681ffc 100644 --- a/src/main/java/chess/controller/status/EndController.java +++ b/src/main/java/chess/controller/status/EndController.java @@ -3,6 +3,9 @@ import chess.controller.Command; public final class EndController implements Controller { + EndController() { + } + @Override public Controller checkCommand(final Command command, final Runnable runnable) { throw new IllegalArgumentException("게임이 끝났습니다."); From 62a1df9b9f8006421a998490a3d2bf1e76a7dd30 Mon Sep 17 00:00:00 2001 From: jiwon Date: Sat, 25 Mar 2023 14:12:13 +0900 Subject: [PATCH 17/76] =?UTF-8?q?feat:=20=ED=82=B9=EC=9D=B4=20=EB=AA=A8?= =?UTF-8?q?=EB=91=90=20=EC=82=B4=EC=95=84=EC=9E=88=EB=8A=94=20=EA=B2=BD?= =?UTF-8?q?=EC=9A=B0=20=EA=B2=8C=EC=9E=84=EC=9D=98=20=EA=B2=B0=EA=B3=BC?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=B4=20=EC=B6=9C=EB=A0=A5=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5=EC=9D=84=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 9 +- .../controller/status/StatusController.java | 55 ++++++++++++ .../status/StatusControllerTest.java | 90 +++++++++++++++++++ 3 files changed, 151 insertions(+), 3 deletions(-) create mode 100644 src/main/java/chess/controller/status/StatusController.java create mode 100644 src/test/java/chess/controller/status/StatusControllerTest.java diff --git a/README.md b/README.md index 3525fa81b69..975fd5d3869 100644 --- a/README.md +++ b/README.md @@ -155,18 +155,21 @@ - [x] 사용자가 입력한 명령어에 따라서 상태를 변경한다. - [x] 사용자가 입력한 명령어가 Start라면 예외를 발생시키고, End라면 종료한다. - - [x] 사용자가 입력한 status이거나 체스판에 살아있는 킹이 없으면 상태를 status로 변경한다. + - [x] 사용자가 입력한 status거나 모든 킹이 살아있는 게 아니라면 상태를 status로 변경한다. - [x] 사용자가 입력한 체스말을 시작 지점에서 끝 지점으로 이동시키고, 차례를 변경한다. - [x] 현재 게임이 실행 중인지 판단한다. ### StartController -- [x] 사용자가 입력한 명령어가 Move라면 예외를 발생시키고, End라면 종료한다. +- [x] 사용자가 입력한 명령어가 move/status라면 예외를 발생시키고, End라면 종료한다. - [x] 현재 게임이 실행 중인지 판단한다. ### StatusController -- [ ] 각 진영의 점수와 이긴 진영을 출력한다. +- [x] 사용자가 입력한 명령어가 start라면 예외를 발생시키고, move면 상태를 move로 변경하고, end라면 종료한다. +- [x] status일 경우 각 진영의 체스판 점수를 계산한다. +- [x] 현재 게임이 실행 중인지 판단한다. +- [x] 현재 살아있는 킹이 없다면 종료 메시지를 출력하고, end로 변경한다. ### PieceName diff --git a/src/main/java/chess/controller/status/StatusController.java b/src/main/java/chess/controller/status/StatusController.java new file mode 100644 index 00000000000..4fdaf474acd --- /dev/null +++ b/src/main/java/chess/controller/status/StatusController.java @@ -0,0 +1,55 @@ +package chess.controller.status; + +import chess.controller.Command; +import chess.controller.dto.ChessResultDto; +import chess.controller.mapper.ChessResultDtoMapper; +import chess.domain.chess.CampType; +import chess.domain.chess.ChessGame; +import chess.domain.chess.ChessGameCalculator; +import chess.view.OutputView; + +public final class StatusController implements Controller { + private final ChessGame chessGame; + private final CampType campType; + + StatusController(final ChessGame chessGame, final CampType campType) { + this.chessGame = chessGame; + this.campType = campType; + } + + @Override + public Controller checkCommand(final Command command, final Runnable runnable) { + if (command.isStart()) { + throw new IllegalArgumentException("이미 시작이 완료되었습니다."); + } + if (command.isEnd()) { + return new EndController(); + } + if (command.isMove()) { + return new MoveController(chessGame, campType).move(command, runnable); + } + return getStatus(true); + } + + @Override + public boolean isRun() { + return true; + } + + Controller getStatus(final boolean isGameRun) { + if (!isGameRun) { + OutputView.print("킹이 사망하여 게임이 종료되었습니다!"); + runCalculator().run(); + return new EndController(); + } + runCalculator().run(); + return this; + } + + private Runnable runCalculator() { + return () -> { + ChessResultDto chessResultDto = ChessResultDtoMapper.from(ChessGameCalculator.calculate(chessGame)); + OutputView.printChessResult(chessResultDto); + }; + } +} diff --git a/src/test/java/chess/controller/status/StatusControllerTest.java b/src/test/java/chess/controller/status/StatusControllerTest.java new file mode 100644 index 00000000000..acf10d74874 --- /dev/null +++ b/src/test/java/chess/controller/status/StatusControllerTest.java @@ -0,0 +1,90 @@ +package chess.controller.status; + +import chess.controller.Command; +import chess.controller.CommandType; +import chess.domain.chess.CampType; +import chess.domain.chess.ChessGame; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class StatusControllerTest { + + @Test + @DisplayName(value = "게임이 status 상태일 때 start를 입력하면 예외가 발생한다.") + void checkCommandStart() { + // given + final StatusController statusController = new StatusController(new ChessGame(), CampType.WHITE); + final Command command = new Command(CommandType.START, List.of("start")); + + // when, then + assertThatThrownBy(() -> statusController.checkCommand(command, () -> { + })) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("이미 시작이 완료되었습니다."); + } + + @Test + @DisplayName(value = "게임이 status 상태일 때 end를 입력하면 게임이 종료된다.") + void checkCommandEnd() { + // given + final StatusController statusController = new StatusController(new ChessGame(), CampType.WHITE); + final Command command = new Command(CommandType.END, List.of("end")); + + // when + Controller controller = statusController.checkCommand(command, () -> { + }); + + // then + assertThat(controller) + .isInstanceOf(EndController.class); + } + + @Test + @DisplayName(value = "게임이 status 상태일 때 move를 입력하면 이동하도록 제어한다.") + void checkCommandMove() { + // given + final StatusController statusController = new StatusController(new ChessGame(), CampType.WHITE); + final Command command = new Command(CommandType.MOVE, List.of("move", "a2", "a4")); + + // when + Controller controller = statusController.checkCommand(command, () -> { + }); + + // then + assertThat(controller) + .isInstanceOf(MoveController.class); + } + + @Test + @DisplayName(value = "게임이 status 상태일 때 실행 중인지 체크하면 true를 반환한다") + void isRun() { + // given + final StatusController statusController = new StatusController(new ChessGame(), CampType.WHITE); + + // when + boolean isRun = statusController.isRun(); + + // then + assertThat(isRun) + .isTrue(); + } + + @Test + @DisplayName("게임이 진행 중인 상태가 아니라면 end 상태로 변경한다.") + void getStatus() { + // given + final StatusController statusController = new StatusController(new ChessGame(), CampType.WHITE); + + // when + Controller controller = statusController.getStatus(false); + + // then + assertThat(controller) + .isInstanceOf(EndController.class); + } +} From ca5389e8788738cd34d2f1b1000576c1e0848717 Mon Sep 17 00:00:00 2001 From: jiwon Date: Sat, 25 Mar 2023 14:12:21 +0900 Subject: [PATCH 18/76] =?UTF-8?q?feat:=20=EA=B2=8C=EC=9E=84=EC=9D=B4=20?= =?UTF-8?q?=EC=9B=80=EC=A7=81=EC=9E=84=20=EC=83=81=ED=83=9C=EC=9D=BC=20?= =?UTF-8?q?=EB=95=8C=20status=EB=A5=BC=20=EC=9E=85=EB=A0=A5=ED=95=98?= =?UTF-8?q?=EB=A9=B4=20=EA=B2=8C=EC=9E=84=20=EA=B2=B0=EA=B3=BC=EB=A5=BC=20?= =?UTF-8?q?=EC=B6=9C=EB=A0=A5=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=A0=9C?= =?UTF-8?q?=EC=96=B4=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/status/MoveController.java | 40 +++++++++++-------- .../controller/status/MoveControllerTest.java | 39 ++++++++++++++++++ 2 files changed, 62 insertions(+), 17 deletions(-) diff --git a/src/main/java/chess/controller/status/MoveController.java b/src/main/java/chess/controller/status/MoveController.java index d17dc744ada..c41c9f14db5 100644 --- a/src/main/java/chess/controller/status/MoveController.java +++ b/src/main/java/chess/controller/status/MoveController.java @@ -12,27 +12,11 @@ public final class MoveController implements Controller { private final ChessGame chessGame; private final CampType campType; - public MoveController(final ChessGame chessGame, final CampType campType) { + MoveController(final ChessGame chessGame, final CampType campType) { this.chessGame = chessGame; this.campType = campType; } - private Controller move(final Command command, final Runnable runnable) { - validateCommand(command); - final List commands = command.getCommands(); - final Position source = PositionConverter.convert(commands.get(1)); - final Position target = PositionConverter.convert(commands.get(2)); - chessGame.setUp(source, target, campType); - runnable.run(); - return new MoveController(chessGame, campType.changeTurn()); - } - - private void validateCommand(final Command command) { - if (!command.isCorrectWhenMove()) { - throw new IllegalArgumentException("'move source위치 target위치 - 예. move b2 b3'와 같은 형태로 입력해 주세요."); - } - } - @Override public Controller checkCommand(final Command command, final Runnable runnable) { if (command.isStart()) { @@ -41,6 +25,9 @@ public Controller checkCommand(final Command command, final Runnable runnable) { if (command.isEnd()) { return new EndController(); } + if (command.isStatus()) { + return new StatusController(chessGame, campType).getStatus(true); + } return move(command, runnable); } @@ -48,4 +35,23 @@ public Controller checkCommand(final Command command, final Runnable runnable) { public boolean isRun() { return true; } + + Controller move(final Command command, final Runnable runnable) { + validateCommand(command); + final List commands = command.getCommands(); + final Position source = PositionConverter.convert(commands.get(1)); + final Position target = PositionConverter.convert(commands.get(2)); + boolean isGameRun = chessGame.run(source, target, campType); + runnable.run(); + if (!isGameRun) { + return new StatusController(chessGame, campType).getStatus(false); + } + return new MoveController(chessGame, campType.changeTurn()); + } + + private void validateCommand(final Command command) { + if (!command.isCorrectWhenMove()) { + throw new IllegalArgumentException("'move source위치 target위치 - 예. move b2 b3'와 같은 형태로 입력해 주세요."); + } + } } diff --git a/src/test/java/chess/controller/status/MoveControllerTest.java b/src/test/java/chess/controller/status/MoveControllerTest.java index 7ae8eebe044..764bf1429d7 100644 --- a/src/test/java/chess/controller/status/MoveControllerTest.java +++ b/src/test/java/chess/controller/status/MoveControllerTest.java @@ -4,6 +4,8 @@ import chess.controller.CommandType; import chess.domain.chess.CampType; import chess.domain.chess.ChessGame; +import chess.domain.chess.ChessGameHelper; +import chess.domain.piece.move.Position; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -47,6 +49,23 @@ void checkCommandEnd() { .isInstanceOf(EndController.class); } + @Test + @DisplayName(value = "게임이 움직임 상태일 때 status를 입력하면 게임 결과를 출력하도록 제어한다.") + void checkCommandStatus() { + // given + final MoveController moveController = new MoveController(new ChessGame(), CampType.WHITE); + final Command command = new Command(CommandType.STATUS, List.of("status")); + + // when + Controller controller = moveController.checkCommand(command, () -> { + }); + + // then + assertThat(controller) + .isInstanceOf(StatusController.class); + } + + @ParameterizedTest(name = "게임이 움직임 상태일 때 올바르지 않은 명령어 형식을 입력하면 예외가 발생한다.") @ValueSource(strings = {"move", "move a2", "", " move ", "move a2 a3 a5", "move a2a3"}) void checkCommandValidate(final String commands) { @@ -61,6 +80,26 @@ void checkCommandValidate(final String commands) { .hasMessage("'move source위치 target위치 - 예. move b2 b3'와 같은 형태로 입력해 주세요."); } + @Test + @DisplayName("게임이 진행 중인 상태가 아니라면 end 상태로 변경한다.") + void move() { + // given + final Command command = new Command(CommandType.MOVE, List.of("move", "b2", "b4")); + final ChessGame chessGame = new ChessGame(); + final CampType campType = CampType.WHITE; + chessGame.run(new Position(1, 0), new Position(3, 0), campType); + ChessGameHelper.playKingDie(chessGame); + final MoveController moveController = new MoveController(chessGame, campType); + + // when + Controller controller = moveController.move(command, () -> { + }); + + // then + assertThat(controller) + .isInstanceOf(EndController.class); + } + @Test @DisplayName(value = "게임이 움직임 상태일 때 실행 중인지 체크하면 true 반환한다") void isRun() { From 3575b9032541caa67503f27171a53622bfb223fb Mon Sep 17 00:00:00 2001 From: jiwon Date: Sun, 26 Mar 2023 15:56:10 +0900 Subject: [PATCH 19/76] =?UTF-8?q?docs:=20=EA=B8=B0=EB=AC=BC=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EA=B8=B0=EB=8A=A5=20=EB=AA=85=EC=84=B8?= =?UTF-8?q?=EC=84=9C=EB=A5=BC=20=EC=88=98=EC=A0=95=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 975fd5d3869..348a25ab9fa 100644 --- a/README.md +++ b/README.md @@ -92,27 +92,27 @@ - [x] 입력받은 위치로 이동시킨다. - [x] 체스말이 이동 가능한 위치를 전부 반환한다. -### QueenMove +### Queen - [x] 입력받은 위치에 대해서 퀸이 이동 가능한지 판단한다. -### RookMove +### Rook - [x] 입력받은 위치에 대해서 룩이 이동 가능한지 판단한다. -### BishopMove +### Bishop - [x] 입력받은 위치에 대해서 비숍이 이동 가능한지 판단한다. -### KingMove +### King - [x] 입력받은 위치에 대해서 킹이 이동 가능한지 판단한다. -### KnightMove +### Knight - [x] 입력받은 위치에 대해서 나이트가 이동 가능한지 판단한다. -### PawnMove +### Pawn - [x] 입력받은 출발 위치의 행보다 도착 위치의 행이 더 크면 UP 방향, 아니면 DOWN 방향으로 이동할 수 있는지 판단한다. From 9f2ba13a59986a1ae22bc0f26d0d06197cd06b6a Mon Sep 17 00:00:00 2001 From: jiwon Date: Sun, 26 Mar 2023 15:59:13 +0900 Subject: [PATCH 20/76] =?UTF-8?q?refactor:=20=EB=AA=85=EB=A0=B9=EC=96=B4?= =?UTF-8?q?=EB=A5=BC=20=EC=9E=85=EB=A0=A5=EB=B0=9B=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=EC=9D=98=20=EB=84=A4=EC=9D=B4=EB=B0=8D=EC=9D=84=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/controller/ChessHandler.java | 2 +- src/main/java/chess/view/InputView.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/chess/controller/ChessHandler.java b/src/main/java/chess/controller/ChessHandler.java index 7ac4c407eb6..c336cbb031c 100644 --- a/src/main/java/chess/controller/ChessHandler.java +++ b/src/main/java/chess/controller/ChessHandler.java @@ -26,7 +26,7 @@ private void start(final ChessGame chessGame) { private Controller play(final ChessGame chessGame, Controller controller) { try { - final List commands = InputView.getCommand(); + final List commands = InputView.getCommands(); final Command command = Command.findCommand(commands); controller = controller.checkCommand(command, () -> OutputView.printBoard( diff --git a/src/main/java/chess/view/InputView.java b/src/main/java/chess/view/InputView.java index 5dbcd5bd9b6..22b1063c440 100644 --- a/src/main/java/chess/view/InputView.java +++ b/src/main/java/chess/view/InputView.java @@ -9,7 +9,7 @@ public final class InputView { private static final String INPUT_ERROR_MESSAGE = "빈 값을 입력할 수 없습니다."; private static final Scanner scanner = new Scanner(System.in); - public static List getCommand() { + public static List getCommands() { final String command = readCommand(); return Arrays.asList(command.split(DELIMITER)); } From 23d07fe74cc1b1ecec2089968dd7a483889ee88b Mon Sep 17 00:00:00 2001 From: jiwon Date: Sun, 26 Mar 2023 17:10:52 +0900 Subject: [PATCH 21/76] =?UTF-8?q?docs:=20=EA=B8=B0=EB=8A=A5=20=EB=AA=85?= =?UTF-8?q?=EC=84=B8=EC=84=9C=EB=A5=BC=20=EC=88=98=EC=A0=95=ED=95=9C?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 231 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 156 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index 348a25ab9fa..4626eb85ab8 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,86 @@ ## ✔ 기능 요구사항 +## ✨ Controller + +### Controller + +- [x] 사용자가 입력한 명령어에 따라 게임의 상태를 확인한다. +- [x] 현재 게임이 실행 중인지 판단한다. + +### EndController + +- [x] 사용자가 입력한 명령어가 End가 아니라면 예외를 발생시킨다. +- [x] 현재 게임이 실행 중인지 판단한다. + +### MoveController + +- [x] 사용자가 입력한 명령어에 따라서 상태를 변경한다. + - [x] 사용자가 입력한 명령어가 Start라면 예외를 발생시키고, End라면 종료한다. + - [x] 사용자가 입력한 status거나 모든 킹이 살아있는 게 아니라면 상태를 status로 변경한다. +- [x] 사용자가 입력한 체스말을 시작 지점에서 끝 지점으로 이동시키고, 차례를 변경한다. +- [x] 현재 게임이 실행 중인지 판단한다. + +### StartController + +- [x] 사용자가 입력한 명령어가 move/status라면 예외를 발생시키고, End라면 종료한다. +- [x] 현재 게임이 실행 중인지 판단한다. + +### StatusController + +- [x] 사용자가 입력한 명령어가 start라면 예외를 발생시키고, move면 상태를 move로 변경하고, end라면 종료한다. +- [x] status일 경우 각 진영의 체스판 점수를 계산한다. +- [x] 현재 게임이 실행 중인지 판단한다. +- [x] 현재 살아있는 킹이 없다면 종료 메시지를 출력하고, end로 변경한다. + +### ChessHandler + +- [x] 체스 게임에 대한 전반적인 실행을 담당한다. + +### Command + +- [x] 사용자가 입력한 명령어에 대해서 관리한다. +- [x] 사용자가 입력한 명령어가 start, move, end인지 검증한다. +- [x] 사용자가 입력한 명령어가 start인지 확인한다. +- [x] 사용자가 입력한 명령어가 end인지 확인한다. +- [x] 사용자가 입력한 명령어가 status인지 확인한다. +- [x] 사용자가 입력한 명령어가 move일 때 올바른 명령어 길이로 들어오는지 확인한다. + +### CommandType + +- [x] 명령어의 종류에 대해서 관리한다. (start, move, end, status) + +--- + +## ✨dao + +### RowMapper + +- [ ] DB에서 조회한 결과에 대해 각 테이블에 맞는 엔티티로 매핑시킨다. + +### UserDao + +- [ ] 사용자의 이름을 기준으로 사용자 엔티티를 조회한다. +- [ ] 사용자의 정보를 삽입한다. + +--- + +## ✨database + +### ChessProperties + +- [ ] DB 연결에 필요한 프로퍼티 정보를 관리한다. + +### JdbcTemplate + +- [ ] 쿼리에 따라 테이블에서 일치하는 결과를 1개만 조회하여 매핑된 결과를 반환한다. +- [ ] 쿼리에 따라 테이블에서 일치하는 결과 전부를 조회하여 매핑된 결과를 반환한다. +- [ ] 쿼리에 따라 테이블에 업데이트 연산 (삽입, 수정, 삭제)을 진행한다. + +--- + +## ✨domain - board + ### ChessBoard - [x] 체스판을 초기화한다. @@ -16,6 +96,18 @@ - [x] 현재 체스판에서 살아있는 킹들을 조회한다. - [x] 입력받은 진영의 체스판을 반환한다. +### ChessBoardFactory + +- [x] 체스판의 초기 상태에 대해서 초기화한다. + +--- + +## ✨domain - chess + +### ScoreVO + +- [x] 각 진영의 체스 결과에 대한 점수를 담는다. + ### ChessGame - [x] 체스 게임을 진행한다. @@ -23,38 +115,32 @@ - [x] WHITE 진영의 체스판을 반환한다. - [x] BLACK 진영의 체스판을 반환한다. -### Score +### CampType -- [x] 점수에 대해서 관리한다. -- [x] 인자로 들어온 점수를 합한 값을 반환한다. -- [x] 인자로 들어온 점수를 뺀 값을 반환한다. -- [x] 인자로 들어온 횟수만큼 곱한 값을 반환한다. +- [x] 사용자의 진영을 관리한다. + - [x] 입력받은 위치의 열이 소문자면 WHITE, 대문자면 BLACK 진영으로 나눈다. +- [x] 플레이할 진영을 번갈아가며 반환한다. ### ChessScoreCalculator - [x] 현재 체스판의 각 진영에 대한 점수를 계산한다. -### CampType +--- -- [x] 사용자의 진영을 관리한다. - - [x] 입력받은 위치의 열이 소문자면 WHITE, 대문자면 BLACK 진영으로 나눈다. -- [x] 플레이할 진영을 번갈아가며 반환한다. +## ✨domain - piece -### Piece +### Direction -- [x] 체스말이 어떤 진영에 속하는지 관리한다. -- [x] 두 개의 체스말이 동일한 진영에 속하는지 판단한다. -- [x] 체스말이 입력받은 진영에 속하는지 판단한다. -- [x] 체스말이 시작 위치에서 도착 위치로 이동 가능한지 판단한다. -- [x] 체스말이 공격 가능한지 판단한다. -- [x] 체스말이 킹인지 판단한다. -- [x] 체스말이 폰인지 판단한다. +- [x] 체스말이 이동하는 방향으로 관리한다. +- [x] 모든 방향에 대해서 반환한다. +- [x] 상하좌우에 대해서 반환한다. +- [x] 상하좌우의 대각선에 대해서 반환한다. -### PieceType +### Location -- [x] 체스말의 종류를 관리한다. -- [x] 특정 체스말이 시작 위치에서 종료 위치까지 이동 가능한지 판단한다. -- [x] 각 체스말의 점수에 대해 관리한다. +- [x] 이동 가능한 모든 위치에 대해 관리한다. +- [x] 이동 가능한 위치에 새로운 정보를 추가한다. +- [x] 이동 가능한 위치에 입력받은 위치가 포함되어 있는지 확인한다. ### Position @@ -69,23 +155,41 @@ - [x] 현재 위치의 rank과 입력받은 위치의 rank가 동일한지 판단한다. - [x] 현재 위치와 입력받은 위치가 동일한지 판단한다. -### Direction +### PositionConverter -- [x] 체스말이 이동하는 방향으로 관리한다. -- [x] 모든 방향에 대해서 반환한다. -- [x] 상하좌우에 대해서 반환한다. -- [x] 상하좌우의 대각선에 대해서 반환한다. +- [x] 입력받은 source, target 위치를 가로, 세로 값으로 분리한다. + - [x] 가로값은 왼쪽부터 0~7 세로값은 아래부터 0~7으로 변환한다. +- [x] 사용자가 입력한 위치를 검증한다. + - [x] 입력받은 위치 명령어의 길이가 2인지 확인한다. + - [x] 첫 번째 글자가 a~h, 두 번째 글자가 1~8인지 확인한다. -### Movable +### Score -- [x] 체스말의 움직임을 관리한다. +- [x] 점수에 대해서 관리한다. +- [x] 인자로 들어온 점수를 합한 값을 반환한다. +- [x] 인자로 들어온 점수를 뺀 값을 반환한다. +- [x] 인자로 들어온 횟수만큼 곱한 값을 반환한다. + +### Piece + +- [x] 체스말이 어떤 진영에 속하는지 관리한다. +- [x] 두 개의 체스말이 동일한 진영에 속하는지 판단한다. +- [x] 체스말이 입력받은 진영에 속하는지 판단한다. +- [x] 체스말이 시작 위치에서 도착 위치로 이동 가능한지 판단한다. - [x] 체스말이 공격 가능한지 판단한다. +- [x] 체스말이 킹인지 판단한다. +- [x] 체스말이 폰인지 판단한다. -### Location +### PieceType -- [x] 이동 가능한 모든 위치에 대해 관리한다. -- [x] 이동 가능한 위치에 새로운 정보를 추가한다. -- [x] 이동 가능한 위치에 입력받은 위치가 포함되어 있는지 확인한다. +- [x] 체스말의 종류를 관리한다. +- [x] 특정 체스말이 시작 위치에서 종료 위치까지 이동 가능한지 판단한다. +- [x] 각 체스말의 점수에 대해 관리한다. + +### Movable + +- [x] 체스말의 움직임을 관리한다. +- [x] 체스말이 공격 가능한지 판단한다. ### Move @@ -116,64 +220,37 @@ - [x] 입력받은 출발 위치의 행보다 도착 위치의 행이 더 크면 UP 방향, 아니면 DOWN 방향으로 이동할 수 있는지 판단한다. -### PositionConverter - -- [x] 입력받은 source, target 위치를 가로, 세로 값으로 분리한다. - - [x] 가로값은 왼쪽부터 0~7 세로값은 아래부터 0~7으로 변환한다. -- [x] 사용자가 입력한 위치를 검증한다. - - [x] 입력받은 위치 명령어의 길이가 2인지 확인한다. - - [x] 첫 번째 글자가 a~h, 두 번째 글자가 1~8인지 확인한다. - -### InputView +--- -- [x] 명령어를 입력받는다. +## ✨domain - user -### Command +### User -- [x] 사용자가 입력한 명령어에 대해서 관리한다. -- [x] 사용자가 입력한 명령어가 start, move, end인지 검증한다. -- [x] 사용자가 입력한 명령어가 start인지 확인한다. -- [x] 사용자가 입력한 명령어가 end인지 확인한다. -- [x] 사용자가 입력한 명령어가 status인지 확인한다. -- [x] 사용자가 입력한 명령어가 move일 때 올바른 명령어 길이로 들어오는지 확인한다. - -### CommandType - -- [x] 명령어의 종류에 대해서 관리한다. (start, move, end, status) +- [ ] 사용자의 이름이 20자 초과라면 예외를 발생시킨다. -### Status +--- -- [x] 사용자가 입력한 명령어에 따라 게임의 상태를 확인한다. -- [x] 현재 게임이 실행 중인지 판단한다. +## ✨domain - entity -### EndController +### UserEntity -- [x] 사용자가 입력한 명령어가 End가 아니라면 예외를 발생시킨다. -- [x] 현재 게임이 실행 중인지 판단한다. +- [ ] user (사용자) 테이블에서 조회한 결과에 대해 담는다. -### MoveController +--- -- [x] 사용자가 입력한 명령어에 따라서 상태를 변경한다. - - [x] 사용자가 입력한 명령어가 Start라면 예외를 발생시키고, End라면 종료한다. - - [x] 사용자가 입력한 status거나 모든 킹이 살아있는 게 아니라면 상태를 status로 변경한다. -- [x] 사용자가 입력한 체스말을 시작 지점에서 끝 지점으로 이동시키고, 차례를 변경한다. -- [x] 현재 게임이 실행 중인지 판단한다. +## ✨domain - service -### StartController +### UserService -- [x] 사용자가 입력한 명령어가 move/status라면 예외를 발생시키고, End라면 종료한다. -- [x] 현재 게임이 실행 중인지 판단한다. +- [ ] 사용자가 입력한 이름이 존재하지 않는 정보면 DB에 삽입하고, 삽입된 사용자의 id를 반환한다. -### StatusController +--- -- [x] 사용자가 입력한 명령어가 start라면 예외를 발생시키고, move면 상태를 move로 변경하고, end라면 종료한다. -- [x] status일 경우 각 진영의 체스판 점수를 계산한다. -- [x] 현재 게임이 실행 중인지 판단한다. -- [x] 현재 살아있는 킹이 없다면 종료 메시지를 출력하고, end로 변경한다. +## ✨domain - view -### PieceName +### InputView -- [x] 체스말의 종류에 따라 체스말의 이름으로 변환한다. +- [x] 명령어를 입력받는다. ### OutputView @@ -182,6 +259,10 @@ - source에 있는 말이 target으로 이동된 체스판을 출력한다. - [x] 각 진영의 점수와 이긴 진영에 대해서 출력한다. +### PieceName + +- [x] 체스말의 종류에 따라 체스말의 이름으로 변환한다. + --- ## ✔ 프로그래밍 요구사항 From 8eee58664379a21ef73b0cb800ed7557daf49bf3 Mon Sep 17 00:00:00 2001 From: jiwon Date: Sun, 26 Mar 2023 17:11:39 +0900 Subject: [PATCH 22/76] =?UTF-8?q?build:=20mysql,=20snakeyaml=20dependency?= =?UTF-8?q?=EB=A5=BC=20=EC=B6=94=EA=B0=80=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.gradle b/build.gradle index a0a012f5798..6afbd4f57c5 100644 --- a/build.gradle +++ b/build.gradle @@ -9,6 +9,8 @@ repositories { } dependencies { + runtimeOnly 'mysql:mysql-connector-java:8.0.28' + implementation 'org.yaml:snakeyaml:2.0' testImplementation 'org.assertj:assertj-core:3.22.0' testImplementation 'org.junit.jupiter:junit-jupiter:5.8.2' } From f886775556d47f72ba0c0fb00377860037bfb370 Mon Sep 17 00:00:00 2001 From: jiwon Date: Sun, 26 Mar 2023 17:12:29 +0900 Subject: [PATCH 23/76] =?UTF-8?q?feat:=20=20DB=20=EC=97=B0=EA=B2=B0?= =?UTF-8?q?=EC=97=90=20=ED=95=84=EC=9A=94=ED=95=9C=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=8D=BC=ED=8B=B0=20=EC=A0=95=EB=B3=B4=EB=A5=BC=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../database/properties/ChessProperties.java | 45 +++++++++++++++++++ src/main/resources/application.yml | 3 ++ 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 src/main/java/chess/database/properties/ChessProperties.java create mode 100644 src/main/resources/application.yml diff --git a/README.md b/README.md index 4626eb85ab8..8f2f7506cdd 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ ### ChessProperties -- [ ] DB 연결에 필요한 프로퍼티 정보를 관리한다. +- [x] DB 연결에 필요한 프로퍼티 정보를 관리한다. ### JdbcTemplate diff --git a/src/main/java/chess/database/properties/ChessProperties.java b/src/main/java/chess/database/properties/ChessProperties.java new file mode 100644 index 00000000000..ba8e974527f --- /dev/null +++ b/src/main/java/chess/database/properties/ChessProperties.java @@ -0,0 +1,45 @@ +package chess.database.properties; + +import org.yaml.snakeyaml.Yaml; + +import java.io.FileReader; +import java.io.IOException; +import java.util.Map; + +public final class ChessProperties { + private static final String URL = "url"; + private static final String USERNAME = "username"; + private static final String PASSWORD = "password"; + + private final String url; + private final String userName; + private final String password; + + public ChessProperties() { + final Map properties = getProperties(); + this.url = properties.get(URL); + this.userName = properties.get(USERNAME); + this.password = properties.get(PASSWORD); + } + + private Map getProperties() { + try (final FileReader fileReader = new FileReader("src/main/resources/application.yml")) { + return new Yaml().load(fileReader); + } catch (IOException e) { + System.out.println("properties read Exception! = " + e.getMessage()); + throw new RuntimeException(e); + } + } + + public String getUrl() { + return url; + } + + public String getUserName() { + return userName; + } + + public String getPassword() { + return password; + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 00000000000..2fba60dfe58 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,3 @@ +url: jdbc:mysql://localhost:13306/chess?useSSL=false&serverTimezone=UTC +username: root +password: root From 74cfdd17411c6b5722fa6b506d12a1ae2965dd73 Mon Sep 17 00:00:00 2001 From: jiwon Date: Sun, 26 Mar 2023 17:13:41 +0900 Subject: [PATCH 24/76] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EC=9D=98=20=EC=9D=B4=EB=A6=84=20=EA=B8=B8=EC=9D=B4=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EA=B2=80=EC=A6=9D=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=EC=9D=84=20=EC=B6=94=EA=B0=80=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/chess/domain/user/User.java | 27 +++++++++++++++++++ src/test/java/chess/domain/user/UserTest.java | 17 ++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/main/java/chess/domain/user/User.java create mode 100644 src/test/java/chess/domain/user/UserTest.java diff --git a/README.md b/README.md index 8f2f7506cdd..9f0116b3417 100644 --- a/README.md +++ b/README.md @@ -226,7 +226,7 @@ ### User -- [ ] 사용자의 이름이 20자 초과라면 예외를 발생시킨다. +- [x] 사용자의 이름이 20자 초과라면 예외를 발생시킨다. --- diff --git a/src/main/java/chess/domain/user/User.java b/src/main/java/chess/domain/user/User.java new file mode 100644 index 00000000000..77f0e9b4e32 --- /dev/null +++ b/src/main/java/chess/domain/user/User.java @@ -0,0 +1,27 @@ +package chess.domain.user; + +public class User { + private static final int MIN_LENGTH = 1; + private static final int MAX_LENGTH = 20; + + private final String name; + + private User(final String name) { + this.name = name; + } + + public static User create(final String name) { + validateLength(name); + return new User(name); + } + + private static void validateLength(final String name) { + if (name.length() < MIN_LENGTH || name.length() > MAX_LENGTH) { + throw new IllegalArgumentException(String.format("이름은 %d~%d글자 사이여야 합니다.", MIN_LENGTH, MAX_LENGTH)); + } + } + + public String getName() { + return name; + } +} diff --git a/src/test/java/chess/domain/user/UserTest.java b/src/test/java/chess/domain/user/UserTest.java new file mode 100644 index 00000000000..2016070168e --- /dev/null +++ b/src/test/java/chess/domain/user/UserTest.java @@ -0,0 +1,17 @@ +package chess.domain.user; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + +class UserTest { + + @ParameterizedTest(name = "사용자의 이름이 1~20자 이내가 아니라면 예외가 발생한다.") + @ValueSource(strings = {"abcdeabcdeabcdeabcdea", ""}) + void create(final String name) { + assertThatThrownBy(() -> User.create(name)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("이름은 1~20글자 사이여야 합니다."); + } +} From ec032ea221ecf4884dd69fc47be6d01bf9d8c8d8 Mon Sep 17 00:00:00 2001 From: jiwon Date: Sun, 26 Mar 2023 17:38:29 +0900 Subject: [PATCH 25/76] =?UTF-8?q?feat:=20=EC=BF=BC=EB=A6=AC=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=9D=BC=201=EA=B0=9C=EC=9D=98=20=EA=B2=B0=EA=B3=BC?= =?UTF-8?q?=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=EC=9D=84=20=EC=B6=94=EA=B0=80=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +-- src/main/java/chess/dao/mapper/RowMapper.java | 9 ++++ .../java/chess/database/JdbcTemplate.java | 49 +++++++++++++++++++ 3 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 src/main/java/chess/dao/mapper/RowMapper.java create mode 100644 src/main/java/chess/database/JdbcTemplate.java diff --git a/README.md b/README.md index 9f0116b3417..cadcabc2c6a 100644 --- a/README.md +++ b/README.md @@ -59,9 +59,9 @@ ### RowMapper -- [ ] DB에서 조회한 결과에 대해 각 테이블에 맞는 엔티티로 매핑시킨다. +- [x] DB에서 조회한 결과에 대해 각 테이블에 맞는 엔티티로 매핑시킨다. -### UserDao +### UserDaoImpl - [ ] 사용자의 이름을 기준으로 사용자 엔티티를 조회한다. - [ ] 사용자의 정보를 삽입한다. @@ -76,7 +76,7 @@ ### JdbcTemplate -- [ ] 쿼리에 따라 테이블에서 일치하는 결과를 1개만 조회하여 매핑된 결과를 반환한다. +- [x] 쿼리에 따라 테이블에서 일치하는 결과를 1개만 조회하여 매핑된 결과를 반환한다. - [ ] 쿼리에 따라 테이블에서 일치하는 결과 전부를 조회하여 매핑된 결과를 반환한다. - [ ] 쿼리에 따라 테이블에 업데이트 연산 (삽입, 수정, 삭제)을 진행한다. diff --git a/src/main/java/chess/dao/mapper/RowMapper.java b/src/main/java/chess/dao/mapper/RowMapper.java new file mode 100644 index 00000000000..d0b0e0fc325 --- /dev/null +++ b/src/main/java/chess/dao/mapper/RowMapper.java @@ -0,0 +1,9 @@ +package chess.dao.mapper; + +import java.sql.ResultSet; +import java.sql.SQLException; + +@FunctionalInterface +public interface RowMapper { + T mapRow(final ResultSet resultSet) throws SQLException; +} diff --git a/src/main/java/chess/database/JdbcTemplate.java b/src/main/java/chess/database/JdbcTemplate.java new file mode 100644 index 00000000000..147ebde0e2a --- /dev/null +++ b/src/main/java/chess/database/JdbcTemplate.java @@ -0,0 +1,49 @@ +package chess.database; + +import chess.dao.mapper.RowMapper; +import chess.database.properties.ChessProperties; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Optional; + +public final class JdbcTemplate { + private final ChessProperties chessProperties; + + public JdbcTemplate(final ChessProperties chessProperties) { + this.chessProperties = chessProperties; + } + + public Optional findOne(final String query, + final RowMapper rowMapper, + final String... params) { + try (final Connection connection = getConnection(); + final PreparedStatement preparedStatement = connection.prepareStatement(query)) { + for (int i = 0; i < params.length; i++) { + preparedStatement.setString(i + 1, params[i]); + } + + final ResultSet resultSet = preparedStatement.executeQuery(); + if (!resultSet.next()) { + return Optional.empty(); + } + return Optional.ofNullable(rowMapper.mapRow(resultSet)); + } catch (SQLException e) { + System.out.println("SQL Exception! = " + e.getMessage()); + throw new RuntimeException(e); + } + } + + private Connection getConnection() { + try { + return DriverManager.getConnection(chessProperties.getUrl(), + chessProperties.getUserName(), chessProperties.getPassword()); + } catch (final SQLException e) { + System.out.println("DB Connection Exception! = " + e.getMessage()); + throw new RuntimeException(e); + } + } +} From 265e0d2c496ece5c942d38df1a27e600a5fbdef5 Mon Sep 17 00:00:00 2001 From: jiwon Date: Sun, 26 Mar 2023 17:43:12 +0900 Subject: [PATCH 26/76] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EC=9D=98=20=EC=9D=B4=EB=A6=84=EC=9D=84=20=EA=B8=B0=EC=A4=80?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=9C?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/chess/dao/user/UserDao.java | 9 ++++ src/main/java/chess/dao/user/UserDaoImpl.java | 24 +++++++++++ src/main/java/chess/entity/UserEntity.java | 26 ++++++++++++ src/test/java/chess/dao/MockUserDao.java | 16 +++++++ src/test/java/chess/dao/UserDaoImplTest.java | 42 +++++++++++++++++++ 6 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 src/main/java/chess/dao/user/UserDao.java create mode 100644 src/main/java/chess/dao/user/UserDaoImpl.java create mode 100644 src/main/java/chess/entity/UserEntity.java create mode 100644 src/test/java/chess/dao/MockUserDao.java create mode 100644 src/test/java/chess/dao/UserDaoImplTest.java diff --git a/README.md b/README.md index cadcabc2c6a..1378a7ba3e6 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ ### UserDaoImpl -- [ ] 사용자의 이름을 기준으로 사용자 엔티티를 조회한다. +- [x] 사용자의 이름을 기준으로 사용자 엔티티를 조회한다. - [ ] 사용자의 정보를 삽입한다. --- diff --git a/src/main/java/chess/dao/user/UserDao.java b/src/main/java/chess/dao/user/UserDao.java new file mode 100644 index 00000000000..0e94b601e73 --- /dev/null +++ b/src/main/java/chess/dao/user/UserDao.java @@ -0,0 +1,9 @@ +package chess.dao.user; + +import chess.entity.UserEntity; + +import java.util.Optional; + +public interface UserDao { + Optional findByName(final String name); +} diff --git a/src/main/java/chess/dao/user/UserDaoImpl.java b/src/main/java/chess/dao/user/UserDaoImpl.java new file mode 100644 index 00000000000..7012ad128d4 --- /dev/null +++ b/src/main/java/chess/dao/user/UserDaoImpl.java @@ -0,0 +1,24 @@ +package chess.dao.user; + +import chess.database.JdbcTemplate; +import chess.entity.UserEntity; + +import java.util.Optional; + +public class UserDaoImpl implements UserDao { + + private final JdbcTemplate jdbcTemplate; + + public UserDaoImpl(final JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Override + public Optional findByName(final String name) { + final String query = "SELECT * FROM user WHERE user_name = ?"; + return jdbcTemplate.findOne(query, (resultSet -> new UserEntity( + resultSet.getLong("user_id"), + resultSet.getString("user_name")) + ), name); + } +} diff --git a/src/main/java/chess/entity/UserEntity.java b/src/main/java/chess/entity/UserEntity.java new file mode 100644 index 00000000000..be6a9e737af --- /dev/null +++ b/src/main/java/chess/entity/UserEntity.java @@ -0,0 +1,26 @@ +package chess.entity; + +import java.util.Objects; + +public class UserEntity { + private final Long id; + private final String name; + + public UserEntity(final Long id, final String name) { + this.id = id; + this.name = name; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final UserEntity that = (UserEntity) o; + return Objects.equals(id, that.id) && Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } +} diff --git a/src/test/java/chess/dao/MockUserDao.java b/src/test/java/chess/dao/MockUserDao.java new file mode 100644 index 00000000000..f8fefb2b1ea --- /dev/null +++ b/src/test/java/chess/dao/MockUserDao.java @@ -0,0 +1,16 @@ +package chess.dao; + +import chess.dao.user.UserDao; +import chess.entity.UserEntity; + +import java.util.Optional; + +public class MockUserDao implements UserDao { + @Override + public Optional findByName(final String name) { + if (name.equals("journey")) { + return Optional.of(new UserEntity(1L, "journey")); + } + return Optional.empty(); + } +} diff --git a/src/test/java/chess/dao/UserDaoImplTest.java b/src/test/java/chess/dao/UserDaoImplTest.java new file mode 100644 index 00000000000..3e5043235a0 --- /dev/null +++ b/src/test/java/chess/dao/UserDaoImplTest.java @@ -0,0 +1,42 @@ +package chess.dao; + +import chess.dao.user.UserDao; +import chess.entity.UserEntity; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Optional; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +class UserDaoImplTest { + + @Test + @DisplayName("사용자가 입력한 이름이 존재하면 해당 이름을 가진 User 엔티티를 반환한다.") + void findByName() { + // given + final UserDao userDao = new MockUserDao(); + final UserEntity expected = new UserEntity(1L, "journey"); + + // when + final Optional userEntity = userDao.findByName("journey"); + final UserEntity actual = userEntity.get(); + + // then + assertThat(actual) + .isEqualTo(expected); + } + + @Test + @DisplayName("사용자가 입력한 이름이 존재하지 않으면 빈 객체를 반환한다.") + void findByNameEmpty() { + // given + final UserDao userDao = new MockUserDao(); + + // when + final Optional userEntity = userDao.findByName("pobi"); + + assertThat(userEntity) + .isEqualTo(Optional.empty()); + } +} From 737f81d2eac98519770ce81e664f078fe494694b Mon Sep 17 00:00:00 2001 From: jiwon Date: Sun, 26 Mar 2023 17:44:18 +0900 Subject: [PATCH 27/76] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EC=9D=98=20=EC=A0=95=EB=B3=B4=EB=A5=BC=20=EC=82=BD=EC=9E=85?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=EC=9D=84=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/chess/dao/user/UserDao.java | 2 ++ src/main/java/chess/dao/user/UserDaoImpl.java | 6 +++++ .../java/chess/database/JdbcTemplate.java | 23 ++++++++++++++++++- src/test/java/chess/dao/MockUserDao.java | 5 ++++ src/test/java/chess/dao/UserDaoImplTest.java | 14 +++++++++++ 6 files changed, 50 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1378a7ba3e6..faabce1e9f3 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ ### UserDaoImpl - [x] 사용자의 이름을 기준으로 사용자 엔티티를 조회한다. -- [ ] 사용자의 정보를 삽입한다. +- [x] 사용자의 정보를 삽입한다. --- diff --git a/src/main/java/chess/dao/user/UserDao.java b/src/main/java/chess/dao/user/UserDao.java index 0e94b601e73..baf77003884 100644 --- a/src/main/java/chess/dao/user/UserDao.java +++ b/src/main/java/chess/dao/user/UserDao.java @@ -6,4 +6,6 @@ public interface UserDao { Optional findByName(final String name); + + Long insert(final String name); } diff --git a/src/main/java/chess/dao/user/UserDaoImpl.java b/src/main/java/chess/dao/user/UserDaoImpl.java index 7012ad128d4..703a59bf755 100644 --- a/src/main/java/chess/dao/user/UserDaoImpl.java +++ b/src/main/java/chess/dao/user/UserDaoImpl.java @@ -21,4 +21,10 @@ public Optional findByName(final String name) { resultSet.getString("user_name")) ), name); } + + @Override + public Long insert(final String name) { + final String query = "INSERT INTO user(user_name) VALUES(?)"; + return jdbcTemplate.executeUpdate(query, name); + } } diff --git a/src/main/java/chess/database/JdbcTemplate.java b/src/main/java/chess/database/JdbcTemplate.java index 147ebde0e2a..c1e15c01aba 100644 --- a/src/main/java/chess/database/JdbcTemplate.java +++ b/src/main/java/chess/database/JdbcTemplate.java @@ -36,7 +36,28 @@ public Optional findOne(final String query, throw new RuntimeException(e); } } - + + public Long executeUpdate(final String query, + final String... params) { + try (final Connection connection = getConnection(); + final PreparedStatement preparedStatement = connection.prepareStatement(query)) { + + for (int i = 0; i < params.length; i++) { + preparedStatement.setString(i + 1, params[i]); + } + preparedStatement.executeUpdate(); + + final ResultSet generatedKeys = preparedStatement.getGeneratedKeys(); + if (!generatedKeys.next()) { + throw new SQLException("Update Exception! - generated key error."); + } + return generatedKeys.getLong(1); + } catch (SQLException e) { + System.out.println("SQL Exception! = " + e.getMessage()); + throw new RuntimeException(e); + } + } + private Connection getConnection() { try { return DriverManager.getConnection(chessProperties.getUrl(), diff --git a/src/test/java/chess/dao/MockUserDao.java b/src/test/java/chess/dao/MockUserDao.java index f8fefb2b1ea..0df4b295cf1 100644 --- a/src/test/java/chess/dao/MockUserDao.java +++ b/src/test/java/chess/dao/MockUserDao.java @@ -13,4 +13,9 @@ public Optional findByName(final String name) { } return Optional.empty(); } + + @Override + public Long insert(final String name) { + return 1L; + } } diff --git a/src/test/java/chess/dao/UserDaoImplTest.java b/src/test/java/chess/dao/UserDaoImplTest.java index 3e5043235a0..5a30070bbdb 100644 --- a/src/test/java/chess/dao/UserDaoImplTest.java +++ b/src/test/java/chess/dao/UserDaoImplTest.java @@ -39,4 +39,18 @@ void findByNameEmpty() { assertThat(userEntity) .isEqualTo(Optional.empty()); } + + @Test + @DisplayName("사용자 정보를 삽입하면, 삽입된 사용자의 아이디를 반환한다.") + void insert() { + // given + final UserDao userDao = new MockUserDao(); + + // when + Long userId = userDao.insert("journey"); + + // then + assertThat(userId) + .isEqualTo(1L); + } } From 832eba934121d072eb0be75871590f1dd0da9c0c Mon Sep 17 00:00:00 2001 From: jiwon Date: Sun, 26 Mar 2023 17:53:18 +0900 Subject: [PATCH 28/76] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EA=B0=80=20=EC=9E=85=EB=A0=A5=ED=95=9C=20=EC=9D=B4=EB=A6=84?= =?UTF-8?q?=EC=9D=B4=20=EC=9D=B4=EB=AF=B8=20=EC=A1=B4=EC=9E=AC=ED=95=98?= =?UTF-8?q?=EB=8A=94=EC=A7=80=20=EA=B2=80=EC=A6=9D=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 ++- src/main/java/chess/script/docker-compose.yml | 18 ++++++++++++++ src/main/java/chess/script/table.sql | 7 ++++++ src/main/java/chess/service/UserService.java | 24 +++++++++++++++++++ .../java/chess/service/UserServiceTest.java | 22 +++++++++++++++++ 5 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/main/java/chess/script/docker-compose.yml create mode 100644 src/main/java/chess/script/table.sql create mode 100644 src/main/java/chess/service/UserService.java create mode 100644 src/test/java/chess/service/UserServiceTest.java diff --git a/README.md b/README.md index faabce1e9f3..a455e418dae 100644 --- a/README.md +++ b/README.md @@ -242,7 +242,8 @@ ### UserService -- [ ] 사용자가 입력한 이름이 존재하지 않는 정보면 DB에 삽입하고, 삽입된 사용자의 id를 반환한다. +- [x] 사용자가 입력한 이름이 이미 존재하는지 검증한다. +- [ ] 사용자의 이름을 바탕으로 사용자의 정보를 삽입한다. --- diff --git a/src/main/java/chess/script/docker-compose.yml b/src/main/java/chess/script/docker-compose.yml new file mode 100644 index 00000000000..558a1d5a53f --- /dev/null +++ b/src/main/java/chess/script/docker-compose.yml @@ -0,0 +1,18 @@ +version: "3.9" +services: + db: + image: mysql:8.0.28 + platform: linux/x86_64 + 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/script/table.sql b/src/main/java/chess/script/table.sql new file mode 100644 index 00000000000..c86ed24bc01 --- /dev/null +++ b/src/main/java/chess/script/table.sql @@ -0,0 +1,7 @@ +-- user +CREATE TABLE user +( + user_id BIGINT(20) NOT NULL AUTO_INCREMENT, + user_name varchar(255) UNIQUE NOT NULL, + PRIMARY KEY (user_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; diff --git a/src/main/java/chess/service/UserService.java b/src/main/java/chess/service/UserService.java new file mode 100644 index 00000000000..5c327878853 --- /dev/null +++ b/src/main/java/chess/service/UserService.java @@ -0,0 +1,24 @@ +package chess.service; + +import chess.dao.user.UserDao; +import chess.domain.user.User; +import chess.entity.UserEntity; + +import java.util.Optional; + +public class UserService { + private final UserDao userDao; + + public UserService(final UserDao userDao) { + this.userDao = userDao; + } + + public void validateDuplicate(final String name) { + final User user = User.create(name); + final String userName = user.getName(); + final Optional userEntity = userDao.findByName(userName); + if (userEntity.isPresent()) { + throw new IllegalArgumentException("이미 존재하는 사용자입니다. 다른 이름을 입력해 주세요."); + } + } +} diff --git a/src/test/java/chess/service/UserServiceTest.java b/src/test/java/chess/service/UserServiceTest.java new file mode 100644 index 00000000000..cf89408553e --- /dev/null +++ b/src/test/java/chess/service/UserServiceTest.java @@ -0,0 +1,22 @@ +package chess.service; + +import chess.dao.MockUserDao; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + +class UserServiceTest { + + @Test + @DisplayName("사용자의 이름이 이미 저장되어 있다면, 예외를 발생시킨다.") + void validateDuplicate() { + // given + final UserService userService = new UserService(new MockUserDao()); + + // when, then + assertThatThrownBy(() -> userService.validateDuplicate("journey")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("이미 존재하는 사용자입니다. 다른 이름을 입력해 주세요."); + } +} From 0661b081287513c2742020b622d11f123b3335c8 Mon Sep 17 00:00:00 2001 From: jiwon Date: Sun, 26 Mar 2023 18:01:03 +0900 Subject: [PATCH 29/76] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EC=9D=98=20=EC=9D=B4=EB=A6=84=EC=9D=84=20=EB=B0=94=ED=83=95?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=82=AC=EC=9A=A9=EC=9E=90=EC=9D=98=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=EB=A5=BC=20=EC=82=BD=EC=9E=85=ED=95=9C?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/chess/service/UserService.java | 4 ++++ src/test/java/chess/service/UserServiceTest.java | 15 +++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a455e418dae..51f983ac6d2 100644 --- a/README.md +++ b/README.md @@ -243,7 +243,7 @@ ### UserService - [x] 사용자가 입력한 이름이 이미 존재하는지 검증한다. -- [ ] 사용자의 이름을 바탕으로 사용자의 정보를 삽입한다. +- [x] 사용자의 이름을 바탕으로 사용자의 정보를 삽입한다. --- diff --git a/src/main/java/chess/service/UserService.java b/src/main/java/chess/service/UserService.java index 5c327878853..c3a07b66fdd 100644 --- a/src/main/java/chess/service/UserService.java +++ b/src/main/java/chess/service/UserService.java @@ -21,4 +21,8 @@ public void validateDuplicate(final String name) { throw new IllegalArgumentException("이미 존재하는 사용자입니다. 다른 이름을 입력해 주세요."); } } + + public Long insert(final String name) { + return userDao.insert(name); + } } diff --git a/src/test/java/chess/service/UserServiceTest.java b/src/test/java/chess/service/UserServiceTest.java index cf89408553e..3b8ecc5d491 100644 --- a/src/test/java/chess/service/UserServiceTest.java +++ b/src/test/java/chess/service/UserServiceTest.java @@ -4,6 +4,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; class UserServiceTest { @@ -19,4 +20,18 @@ void validateDuplicate() { .isInstanceOf(IllegalArgumentException.class) .hasMessage("이미 존재하는 사용자입니다. 다른 이름을 입력해 주세요."); } + + @Test + @DisplayName("사용자의 이름에 따라 사용자의 정보를 삽입한다.") + void insert() { + // given + final UserService userService = new UserService(new MockUserDao()); + + // when + Long userId = userService.insert("journey"); + + // then + assertThat(userId) + .isEqualTo(1L); + } } From 618bd08e9cf603579f631bff27e7aaecb75b6859 Mon Sep 17 00:00:00 2001 From: jiwon Date: Sun, 26 Mar 2023 18:30:16 +0900 Subject: [PATCH 30/76] =?UTF-8?q?fix:=20=EC=9E=90=EB=8F=99=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=83=9D=EC=84=B1=EB=90=9C=20=ED=82=A4=EB=A5=BC=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=98=B5?= =?UTF-8?q?=EC=85=98=EC=9D=84=20=EC=B6=94=EA=B0=80=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/database/JdbcTemplate.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/chess/database/JdbcTemplate.java b/src/main/java/chess/database/JdbcTemplate.java index c1e15c01aba..743b30c978a 100644 --- a/src/main/java/chess/database/JdbcTemplate.java +++ b/src/main/java/chess/database/JdbcTemplate.java @@ -8,6 +8,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Statement; import java.util.Optional; public final class JdbcTemplate { @@ -40,7 +41,8 @@ public Optional findOne(final String query, public Long executeUpdate(final String query, final String... params) { try (final Connection connection = getConnection(); - final PreparedStatement preparedStatement = connection.prepareStatement(query)) { + final PreparedStatement preparedStatement = connection.prepareStatement( + query, Statement.RETURN_GENERATED_KEYS)) { for (int i = 0; i < params.length; i++) { preparedStatement.setString(i + 1, params[i]); From a0fba3ca032fb1d6731870e253cc5aa503918fbf Mon Sep 17 00:00:00 2001 From: jiwon Date: Sun, 26 Mar 2023 18:46:54 +0900 Subject: [PATCH 31/76] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EC=9D=98=20=EC=A0=95=EB=B3=B4=EA=B0=80=20=EC=9D=B4=EB=AF=B8=20?= =?UTF-8?q?=EC=A1=B4=EC=9E=AC=ED=95=A0=20=EA=B2=BD=EC=9A=B0=20=EC=A1=B4?= =?UTF-8?q?=EC=9E=AC=ED=95=98=EB=8A=94=20=EC=95=84=EC=9D=B4=EB=94=94?= =?UTF-8?q?=EB=A5=BC=20=EB=B0=98=ED=99=98=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/chess/entity/UserEntity.java | 4 ++++ src/main/java/chess/service/UserService.java | 7 +++--- src/test/java/chess/dao/MockUserDao.java | 5 +++- .../java/chess/service/UserServiceTest.java | 23 ++++++++++--------- 5 files changed, 25 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 51f983ac6d2..444b4258136 100644 --- a/README.md +++ b/README.md @@ -242,7 +242,7 @@ ### UserService -- [x] 사용자가 입력한 이름이 이미 존재하는지 검증한다. +- [x] 사용자가 입력한 이름이 이미 존재한다면 해당 사용자의 아이디를, 아니라면 새롭게 삽입 후 생성된 아이디를 반환한다. - [x] 사용자의 이름을 바탕으로 사용자의 정보를 삽입한다. --- diff --git a/src/main/java/chess/entity/UserEntity.java b/src/main/java/chess/entity/UserEntity.java index be6a9e737af..fd1f0725f65 100644 --- a/src/main/java/chess/entity/UserEntity.java +++ b/src/main/java/chess/entity/UserEntity.java @@ -23,4 +23,8 @@ public boolean equals(final Object o) { public int hashCode() { return Objects.hash(id, name); } + + public Long getId() { + return id; + } } diff --git a/src/main/java/chess/service/UserService.java b/src/main/java/chess/service/UserService.java index c3a07b66fdd..3fa2e3e43b1 100644 --- a/src/main/java/chess/service/UserService.java +++ b/src/main/java/chess/service/UserService.java @@ -13,16 +13,17 @@ public UserService(final UserDao userDao) { this.userDao = userDao; } - public void validateDuplicate(final String name) { + public Long getUserId(final String name) { final User user = User.create(name); final String userName = user.getName(); final Optional userEntity = userDao.findByName(userName); if (userEntity.isPresent()) { - throw new IllegalArgumentException("이미 존재하는 사용자입니다. 다른 이름을 입력해 주세요."); + return userEntity.get().getId(); } + return insert(name); } - public Long insert(final String name) { + private Long insert(final String name) { return userDao.insert(name); } } diff --git a/src/test/java/chess/dao/MockUserDao.java b/src/test/java/chess/dao/MockUserDao.java index 0df4b295cf1..8bafb429477 100644 --- a/src/test/java/chess/dao/MockUserDao.java +++ b/src/test/java/chess/dao/MockUserDao.java @@ -16,6 +16,9 @@ public Optional findByName(final String name) { @Override public Long insert(final String name) { - return 1L; + if (name.equals("journey")) { + return 1L; + } + return 2L; } } diff --git a/src/test/java/chess/service/UserServiceTest.java b/src/test/java/chess/service/UserServiceTest.java index 3b8ecc5d491..83c58820f02 100644 --- a/src/test/java/chess/service/UserServiceTest.java +++ b/src/test/java/chess/service/UserServiceTest.java @@ -5,33 +5,34 @@ import org.junit.jupiter.api.Test; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; class UserServiceTest { @Test - @DisplayName("사용자의 이름이 이미 저장되어 있다면, 예외를 발생시킨다.") - void validateDuplicate() { + @DisplayName("사용자의 이름이 이미 저장되어 있다면, 존재하는 사용자의 아이디를 반환한다.") + void getUserId_exist() { // given final UserService userService = new UserService(new MockUserDao()); - // when, then - assertThatThrownBy(() -> userService.validateDuplicate("journey")) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("이미 존재하는 사용자입니다. 다른 이름을 입력해 주세요."); + // when + Long userId = userService.getUserId("journey"); + + // then + assertThat(userId) + .isEqualTo(1L); } @Test - @DisplayName("사용자의 이름에 따라 사용자의 정보를 삽입한다.") - void insert() { + @DisplayName("사용자의 이름이 저장되지 않았다면, 새롭게 저장 후 저장된 아이디를 반환한다.") + void getUserId_new() { // given final UserService userService = new UserService(new MockUserDao()); // when - Long userId = userService.insert("journey"); + Long userId = userService.getUserId("hello"); // then assertThat(userId) - .isEqualTo(1L); + .isEqualTo(2L); } } From 113b388302c4ca4171ca0ad85b186d70b0a1f623 Mon Sep 17 00:00:00 2001 From: jiwon Date: Sun, 26 Mar 2023 18:56:24 +0900 Subject: [PATCH 32/76] =?UTF-8?q?refactor:=20=ED=8C=A8=ED=82=A4=EC=A7=80?= =?UTF-8?q?=20=EC=9D=B4=EB=8F=99=EC=9D=84=20=EC=A7=84=ED=96=89=ED=95=9C?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/chess/dao/{ => user}/MockUserDao.java | 3 +-- src/test/java/chess/dao/{ => user}/UserDaoImplTest.java | 3 +-- src/test/java/chess/service/UserServiceTest.java | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) rename src/test/java/chess/dao/{ => user}/MockUserDao.java (90%) rename src/test/java/chess/dao/{ => user}/UserDaoImplTest.java (96%) diff --git a/src/test/java/chess/dao/MockUserDao.java b/src/test/java/chess/dao/user/MockUserDao.java similarity index 90% rename from src/test/java/chess/dao/MockUserDao.java rename to src/test/java/chess/dao/user/MockUserDao.java index 8bafb429477..2afb22c58fa 100644 --- a/src/test/java/chess/dao/MockUserDao.java +++ b/src/test/java/chess/dao/user/MockUserDao.java @@ -1,6 +1,5 @@ -package chess.dao; +package chess.dao.user; -import chess.dao.user.UserDao; import chess.entity.UserEntity; import java.util.Optional; diff --git a/src/test/java/chess/dao/UserDaoImplTest.java b/src/test/java/chess/dao/user/UserDaoImplTest.java similarity index 96% rename from src/test/java/chess/dao/UserDaoImplTest.java rename to src/test/java/chess/dao/user/UserDaoImplTest.java index 5a30070bbdb..3bfc00e285b 100644 --- a/src/test/java/chess/dao/UserDaoImplTest.java +++ b/src/test/java/chess/dao/user/UserDaoImplTest.java @@ -1,6 +1,5 @@ -package chess.dao; +package chess.dao.user; -import chess.dao.user.UserDao; import chess.entity.UserEntity; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/chess/service/UserServiceTest.java b/src/test/java/chess/service/UserServiceTest.java index 83c58820f02..8b66fcaf735 100644 --- a/src/test/java/chess/service/UserServiceTest.java +++ b/src/test/java/chess/service/UserServiceTest.java @@ -1,6 +1,6 @@ package chess.service; -import chess.dao.MockUserDao; +import chess.dao.user.MockUserDao; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; From 3f5eb1988f907a249ed96e90bf8e5fc5e250fe44 Mon Sep 17 00:00:00 2001 From: jiwon Date: Sun, 26 Mar 2023 19:03:35 +0900 Subject: [PATCH 33/76] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EC=9D=98=20=EC=95=84=EC=9D=B4=EB=94=94=EB=A5=BC=20=EA=B8=B0?= =?UTF-8?q?=EC=A4=80=EC=9C=BC=EB=A1=9C=20=EC=B2=B4=EC=8A=A4=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=EC=9D=84=20=EC=A1=B0=ED=9A=8C=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 10 ++++- .../java/chess/dao/chess/ChessGameDao.java | 9 ++++ .../chess/dao/chess/ChessGameDaoImpl.java | 24 ++++++++++ .../java/chess/entity/ChessGameEntity.java | 28 ++++++++++++ src/main/java/chess/script/table.sql | 10 +++++ .../chess/dao/chess/ChessGameDaoImplTest.java | 44 +++++++++++++++++++ .../chess/dao/chess/MockChessGameDao.java | 15 +++++++ 7 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 src/main/java/chess/dao/chess/ChessGameDao.java create mode 100644 src/main/java/chess/dao/chess/ChessGameDaoImpl.java create mode 100644 src/main/java/chess/entity/ChessGameEntity.java create mode 100644 src/test/java/chess/dao/chess/ChessGameDaoImplTest.java create mode 100644 src/test/java/chess/dao/chess/MockChessGameDao.java diff --git a/README.md b/README.md index 444b4258136..f695f4667df 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,10 @@ - [x] 사용자의 이름을 기준으로 사용자 엔티티를 조회한다. - [x] 사용자의 정보를 삽입한다. +### ChessGameDaoImpl + +- [x] 사용자의 아이디를 기준으로 체스 게임을 조회한다. + --- ## ✨database @@ -234,7 +238,11 @@ ### UserEntity -- [ ] user (사용자) 테이블에서 조회한 결과에 대해 담는다. +- [x] user (사용자) 테이블에서 조회한 결과에 대해 담는다. + +### ChessGameEntity + +- [x] chess_game (체스 게임) 테이블에서 조회한 결과에 대해 담는다. --- diff --git a/src/main/java/chess/dao/chess/ChessGameDao.java b/src/main/java/chess/dao/chess/ChessGameDao.java new file mode 100644 index 00000000000..8cecdd9abed --- /dev/null +++ b/src/main/java/chess/dao/chess/ChessGameDao.java @@ -0,0 +1,9 @@ +package chess.dao.chess; + +import chess.entity.ChessGameEntity; + +import java.util.Optional; + +public interface ChessGameDao { + Optional findByUserId(final Long userId); +} diff --git a/src/main/java/chess/dao/chess/ChessGameDaoImpl.java b/src/main/java/chess/dao/chess/ChessGameDaoImpl.java new file mode 100644 index 00000000000..759ca9a4b84 --- /dev/null +++ b/src/main/java/chess/dao/chess/ChessGameDaoImpl.java @@ -0,0 +1,24 @@ +package chess.dao.chess; + +import chess.database.JdbcTemplate; +import chess.entity.ChessGameEntity; + +import java.util.Optional; + +public class ChessGameDaoImpl implements ChessGameDao { + private final JdbcTemplate jdbcTemplate; + + public ChessGameDaoImpl(final JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Override + public Optional findByUserId(final Long userId) { + final String query = "SELECT * FROM chess_game WHERE user_id = ?"; + return jdbcTemplate.findOne(query, (resultSet -> new ChessGameEntity( + resultSet.getLong("chess_game_id"), + resultSet.getString("current_camp"), + resultSet.getLong("user_id")) + ), String.valueOf(userId)); + } +} diff --git a/src/main/java/chess/entity/ChessGameEntity.java b/src/main/java/chess/entity/ChessGameEntity.java new file mode 100644 index 00000000000..e1ef87a6536 --- /dev/null +++ b/src/main/java/chess/entity/ChessGameEntity.java @@ -0,0 +1,28 @@ +package chess.entity; + +import java.util.Objects; + +public class ChessGameEntity { + private final Long id; + private final String currentCamp; + private final Long userId; + + public ChessGameEntity(final Long id, final String currentCamp, final Long userId) { + this.id = id; + this.currentCamp = currentCamp; + this.userId = userId; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final ChessGameEntity that = (ChessGameEntity) o; + return Objects.equals(id, that.id) && Objects.equals(currentCamp, that.currentCamp) && Objects.equals(userId, that.userId); + } + + @Override + public int hashCode() { + return Objects.hash(id, currentCamp, userId); + } +} diff --git a/src/main/java/chess/script/table.sql b/src/main/java/chess/script/table.sql index c86ed24bc01..422c57774b8 100644 --- a/src/main/java/chess/script/table.sql +++ b/src/main/java/chess/script/table.sql @@ -5,3 +5,13 @@ CREATE TABLE user user_name varchar(255) UNIQUE NOT NULL, PRIMARY KEY (user_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- chess_game +CREATE TABLE chess_game +( + chess_game_id BIGINT(20) NOT NULL AUTO_INCREMENT, + current_camp VARCHAR(5) NOT NULL, + user_id BIGINT(20) NOT NULL, + PRIMARY KEY (chess_game_id), + FOREIGN KEY (user_id) REFERENCES user (user_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; diff --git a/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java b/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java new file mode 100644 index 00000000000..d0354afdced --- /dev/null +++ b/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java @@ -0,0 +1,44 @@ +package chess.dao.chess; + +import chess.entity.ChessGameEntity; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Optional; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +class ChessGameDaoImplTest { + + @Test + @DisplayName("사용자의 아이디에 존재하는 체스 게임이 존재하면, 해당 체스 게임을 반환한다.") + void findByUserId() { + // given + final ChessGameDao chessGameDao = new MockChessGameDao(); + final ChessGameEntity expected = new ChessGameEntity(1L, "WHITE", 1L); + final long userId = 1L; + + // when + final Optional chessGameEntity = chessGameDao.findByUserId(userId); + final ChessGameEntity actual = chessGameEntity.get(); + + // then + assertThat(actual) + .isEqualTo(expected); + } + + @Test + @DisplayName("사용자가 아이디에 해당하는 체스 게임이 존재하지 않으면, 빈 객체를 반환한다.") + void findByUserId_empty() { + // given + final ChessGameDao chessGameDao = new MockChessGameDao(); + final long userId = 2L; + + // when + final Optional chessGameEntity = chessGameDao.findByUserId(userId); + + // then + assertThat(chessGameEntity) + .isEqualTo(Optional.empty()); + } +} diff --git a/src/test/java/chess/dao/chess/MockChessGameDao.java b/src/test/java/chess/dao/chess/MockChessGameDao.java new file mode 100644 index 00000000000..dac0fd517f5 --- /dev/null +++ b/src/test/java/chess/dao/chess/MockChessGameDao.java @@ -0,0 +1,15 @@ +package chess.dao.chess; + +import chess.entity.ChessGameEntity; + +import java.util.Optional; + +public class MockChessGameDao implements ChessGameDao { + @Override + public Optional findByUserId(final Long userId) { + if (userId == 1L) { + return Optional.of(new ChessGameEntity(1L, "WHITE", 1L)); + } + return Optional.empty(); + } +} From d5a433488ac759e7b7455a5e870f468427dedd9e Mon Sep 17 00:00:00 2001 From: jiwon Date: Sun, 26 Mar 2023 21:41:51 +0900 Subject: [PATCH 34/76] =?UTF-8?q?feat:=20final=20=ED=82=A4=EC=9B=8C?= =?UTF-8?q?=EB=93=9C=EB=A5=BC=20=EB=B6=99=EC=9D=B8=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/dao/chess/ChessGameDaoImpl.java | 2 +- src/main/java/chess/dao/user/UserDaoImpl.java | 2 +- src/main/java/chess/entity/ChessGameEntity.java | 2 +- src/main/java/chess/entity/UserEntity.java | 2 +- src/main/java/chess/service/UserService.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/chess/dao/chess/ChessGameDaoImpl.java b/src/main/java/chess/dao/chess/ChessGameDaoImpl.java index 759ca9a4b84..646ff3d4fdf 100644 --- a/src/main/java/chess/dao/chess/ChessGameDaoImpl.java +++ b/src/main/java/chess/dao/chess/ChessGameDaoImpl.java @@ -5,7 +5,7 @@ import java.util.Optional; -public class ChessGameDaoImpl implements ChessGameDao { +public final class ChessGameDaoImpl implements ChessGameDao { private final JdbcTemplate jdbcTemplate; public ChessGameDaoImpl(final JdbcTemplate jdbcTemplate) { diff --git a/src/main/java/chess/dao/user/UserDaoImpl.java b/src/main/java/chess/dao/user/UserDaoImpl.java index 703a59bf755..89a5bb57fb0 100644 --- a/src/main/java/chess/dao/user/UserDaoImpl.java +++ b/src/main/java/chess/dao/user/UserDaoImpl.java @@ -5,7 +5,7 @@ import java.util.Optional; -public class UserDaoImpl implements UserDao { +public final class UserDaoImpl implements UserDao { private final JdbcTemplate jdbcTemplate; diff --git a/src/main/java/chess/entity/ChessGameEntity.java b/src/main/java/chess/entity/ChessGameEntity.java index e1ef87a6536..0a7a75b874a 100644 --- a/src/main/java/chess/entity/ChessGameEntity.java +++ b/src/main/java/chess/entity/ChessGameEntity.java @@ -2,7 +2,7 @@ import java.util.Objects; -public class ChessGameEntity { +public final class ChessGameEntity { private final Long id; private final String currentCamp; private final Long userId; diff --git a/src/main/java/chess/entity/UserEntity.java b/src/main/java/chess/entity/UserEntity.java index fd1f0725f65..abdc7ce6e66 100644 --- a/src/main/java/chess/entity/UserEntity.java +++ b/src/main/java/chess/entity/UserEntity.java @@ -2,7 +2,7 @@ import java.util.Objects; -public class UserEntity { +public final class UserEntity { private final Long id; private final String name; diff --git a/src/main/java/chess/service/UserService.java b/src/main/java/chess/service/UserService.java index 3fa2e3e43b1..8e8e0c1a67b 100644 --- a/src/main/java/chess/service/UserService.java +++ b/src/main/java/chess/service/UserService.java @@ -6,7 +6,7 @@ import java.util.Optional; -public class UserService { +public final class UserService { private final UserDao userDao; public UserService(final UserDao userDao) { From beb636353f3331a08726642691a64a70c58016d8 Mon Sep 17 00:00:00 2001 From: jiwon Date: Sun, 26 Mar 2023 22:12:33 +0900 Subject: [PATCH 35/76] =?UTF-8?q?feat:=20=EC=B2=B4=EC=8A=A4=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=20=EC=95=84=EC=9D=B4=EB=94=94=EB=A5=BC=20=EA=B8=B0?= =?UTF-8?q?=EC=A4=80=EC=9C=BC=EB=A1=9C=20=EC=B2=B4=EC=8A=A4=EB=A7=90=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=EC=9D=98=20=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 +++- src/main/java/chess/dao/chess/PieceDao.java | 9 +++++ .../java/chess/dao/chess/PieceDaoImpl.java | 26 +++++++++++++ .../java/chess/database/JdbcTemplate.java | 23 +++++++++++ src/main/java/chess/entity/PieceEntity.java | 33 ++++++++++++++++ .../java/chess/dao/chess/MockPieceDao.java | 20 ++++++++++ .../chess/dao/chess/PieceDaoImplTest.java | 28 +++++++++++++ .../chess/dao/chess/PieceEntityHelper.java | 39 +++++++++++++++++++ 8 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 src/main/java/chess/dao/chess/PieceDao.java create mode 100644 src/main/java/chess/dao/chess/PieceDaoImpl.java create mode 100644 src/main/java/chess/entity/PieceEntity.java create mode 100644 src/test/java/chess/dao/chess/MockPieceDao.java create mode 100644 src/test/java/chess/dao/chess/PieceDaoImplTest.java create mode 100644 src/test/java/chess/dao/chess/PieceEntityHelper.java diff --git a/README.md b/README.md index f695f4667df..5f4a77c11a2 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,10 @@ - [x] 사용자의 아이디를 기준으로 체스 게임을 조회한다. +### PieceDaoImpl + +- [x] 체스 게임 아이디를 기준으로 체스말 리스트의 정보를 조회한다. + --- ## ✨database @@ -81,8 +85,8 @@ ### JdbcTemplate - [x] 쿼리에 따라 테이블에서 일치하는 결과를 1개만 조회하여 매핑된 결과를 반환한다. -- [ ] 쿼리에 따라 테이블에서 일치하는 결과 전부를 조회하여 매핑된 결과를 반환한다. -- [ ] 쿼리에 따라 테이블에 업데이트 연산 (삽입, 수정, 삭제)을 진행한다. +- [x] 쿼리에 따라 테이블에서 일치하는 결과 전부를 조회하여 매핑된 결과를 반환한다. +- [x] 쿼리에 따라 테이블에 업데이트 연산 (삽입, 수정, 삭제)을 진행한다. --- diff --git a/src/main/java/chess/dao/chess/PieceDao.java b/src/main/java/chess/dao/chess/PieceDao.java new file mode 100644 index 00000000000..e9e50d2e71a --- /dev/null +++ b/src/main/java/chess/dao/chess/PieceDao.java @@ -0,0 +1,9 @@ +package chess.dao.chess; + +import chess.entity.PieceEntity; + +import java.util.List; + +public interface PieceDao { + List findByChessGameId(final Long chessGameId); +} diff --git a/src/main/java/chess/dao/chess/PieceDaoImpl.java b/src/main/java/chess/dao/chess/PieceDaoImpl.java new file mode 100644 index 00000000000..c53a3b99b8c --- /dev/null +++ b/src/main/java/chess/dao/chess/PieceDaoImpl.java @@ -0,0 +1,26 @@ +package chess.dao.chess; + +import chess.database.JdbcTemplate; +import chess.entity.PieceEntity; + +import java.util.List; + +public class PieceDaoImpl implements PieceDao { + + private final JdbcTemplate jdbcTemplate; + + public PieceDaoImpl(final JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Override + public List findByChessGameId(final Long chessGameId) { + final String query = "SELECT * FROM piece WHERE chess_game_id = ?"; + return jdbcTemplate.findAll(query, (resultSet -> new PieceEntity( + resultSet.getLong("piece_id"), + resultSet.getInt("piece_rank"), + resultSet.getInt("piece_file"), + resultSet.getString("piece_type"), + resultSet.getString("camp"))), String.valueOf(chessGameId)); + } +} diff --git a/src/main/java/chess/database/JdbcTemplate.java b/src/main/java/chess/database/JdbcTemplate.java index 743b30c978a..daf8c47c1ba 100644 --- a/src/main/java/chess/database/JdbcTemplate.java +++ b/src/main/java/chess/database/JdbcTemplate.java @@ -9,6 +9,8 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; public final class JdbcTemplate { @@ -38,6 +40,27 @@ public Optional findOne(final String query, } } + public List findAll(final String query, + final RowMapper rowMapper, + final String... params) { + try (final Connection connection = getConnection(); + final PreparedStatement preparedStatement = connection.prepareStatement(query)) { + for (int i = 0; i < params.length; i++) { + preparedStatement.setString(i + 1, params[i]); + } + + final List results = new ArrayList<>(); + final ResultSet resultSet = preparedStatement.executeQuery(); + while (resultSet.next()) { + results.add(rowMapper.mapRow(resultSet)); + } + return results; + } catch (SQLException e) { + System.out.println("SQL Exception! = " + e.getMessage()); + throw new RuntimeException(e); + } + } + public Long executeUpdate(final String query, final String... params) { try (final Connection connection = getConnection(); diff --git a/src/main/java/chess/entity/PieceEntity.java b/src/main/java/chess/entity/PieceEntity.java new file mode 100644 index 00000000000..7b12b88413a --- /dev/null +++ b/src/main/java/chess/entity/PieceEntity.java @@ -0,0 +1,33 @@ +package chess.entity; + +import java.util.Objects; + +public final class PieceEntity { + private final Long id; + private final Integer rank; + private final Integer file; + private final String pieceType; + private final String campType; + + public PieceEntity(final Long id, final Integer rank, final Integer file, + final String pieceType, final String campType) { + this.id = id; + this.rank = rank; + this.file = file; + this.pieceType = pieceType; + this.campType = campType; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final PieceEntity that = (PieceEntity) o; + return Objects.equals(id, that.id) && Objects.equals(rank, that.rank) && Objects.equals(file, that.file) && Objects.equals(pieceType, that.pieceType) && Objects.equals(campType, that.campType); + } + + @Override + public int hashCode() { + return Objects.hash(id, rank, file, pieceType, campType); + } +} diff --git a/src/test/java/chess/dao/chess/MockPieceDao.java b/src/test/java/chess/dao/chess/MockPieceDao.java new file mode 100644 index 00000000000..b86156be0e1 --- /dev/null +++ b/src/test/java/chess/dao/chess/MockPieceDao.java @@ -0,0 +1,20 @@ +package chess.dao.chess; + +import chess.entity.PieceEntity; + +import java.util.List; + +public class MockPieceDao implements PieceDao { + + private final List mockPieceEntites; + + public MockPieceDao() { + this.mockPieceEntites = PieceEntityHelper.createPieceEntities(); + + } + + @Override + public List findByChessGameId(final Long chessGameId) { + return List.copyOf(mockPieceEntites); + } +} diff --git a/src/test/java/chess/dao/chess/PieceDaoImplTest.java b/src/test/java/chess/dao/chess/PieceDaoImplTest.java new file mode 100644 index 00000000000..25767a5e067 --- /dev/null +++ b/src/test/java/chess/dao/chess/PieceDaoImplTest.java @@ -0,0 +1,28 @@ +package chess.dao.chess; + +import chess.entity.PieceEntity; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +public class PieceDaoImplTest { + @Test + @DisplayName("체스 게임 아이디를 기준으로 체스말 리스트의 정보를 조회한다.") + void findByChessGameId() { + // given + final PieceDao pieceDao = new MockPieceDao(); + + // when + List pieceEntities = pieceDao.findByChessGameId(1L); + + // then + assertThat(pieceEntities) + .isEqualTo(PieceEntityHelper.createPieceEntities()); + + assertThat(pieceEntities.size()) + .isSameAs(32); + } +} diff --git a/src/test/java/chess/dao/chess/PieceEntityHelper.java b/src/test/java/chess/dao/chess/PieceEntityHelper.java new file mode 100644 index 00000000000..5de93b0c811 --- /dev/null +++ b/src/test/java/chess/dao/chess/PieceEntityHelper.java @@ -0,0 +1,39 @@ +package chess.dao.chess; + +import chess.entity.PieceEntity; + +import java.util.ArrayList; +import java.util.List; + +public class PieceEntityHelper { + + public static List createPieceEntities() { + final List results = new ArrayList<>(); + results.addAll(createMockPieces(1L, 0, "WHITE")); + results.addAll(createMockPawnPieces(9L, 1, "WHITE")); + results.addAll(createMockPawnPieces(17L, 6, "BLACK")); + results.addAll(createMockPieces(25L, 7, "BLACK")); + return results; + } + + private static List createMockPieces(final long id, final int rank, final String campType) { + final List results = new ArrayList<>(); + results.add(new PieceEntity(id, rank, 0, "ROOK", campType)); + results.add(new PieceEntity(id + 1, rank, 1, "KNIGHT", campType)); + results.add(new PieceEntity(id + 2, rank, 2, "BISHOP", campType)); + results.add(new PieceEntity(id + 3, rank, 3, "QUEEN", campType)); + results.add(new PieceEntity(id + 4, rank, 4, "KING", campType)); + results.add(new PieceEntity(id + 5, rank, 5, "BISHOP", campType)); + results.add(new PieceEntity(id + 6, rank, 6, "KNIGHT", campType)); + results.add(new PieceEntity(id + 7, rank, 7, "ROOK", campType)); + return results; + } + + private static List createMockPawnPieces(final long id, final int rank, final String campType) { + final List results = new ArrayList<>(); + for (int file = 0; file < 8; file++) { + results.add(new PieceEntity(id + file, rank, file, "PAWN", campType)); + } + return results; + } +} From cb34b70d9d267c4a3b5401a84c23775d0355283c Mon Sep 17 00:00:00 2001 From: jiwon Date: Sun, 26 Mar 2023 23:13:12 +0900 Subject: [PATCH 36/76] =?UTF-8?q?feat:=20pieceEntity=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=B2=B4=EC=8A=A4=ED=8C=90=EC=9D=84=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=ED=95=98=EB=8A=94=20mapper=20class=EB=A5=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/chess/domain/chess/CampType.java | 13 ++++++++ .../java/chess/domain/piece/PieceType.java | 13 ++++++++ src/main/java/chess/entity/PieceEntity.java | 16 ++++++++++ .../service/mapper/ChessBoardMapper.java | 27 ++++++++++++++++ .../chess/service/mapper/MovableMapper.java | 31 +++++++++++++++++++ 5 files changed, 100 insertions(+) create mode 100644 src/main/java/chess/service/mapper/ChessBoardMapper.java create mode 100644 src/main/java/chess/service/mapper/MovableMapper.java diff --git a/src/main/java/chess/domain/chess/CampType.java b/src/main/java/chess/domain/chess/CampType.java index b355421287a..3917462e828 100644 --- a/src/main/java/chess/domain/chess/CampType.java +++ b/src/main/java/chess/domain/chess/CampType.java @@ -1,9 +1,13 @@ package chess.domain.chess; +import java.util.Arrays; + public enum CampType { BLACK, WHITE; + private static final String ERROR_MESSAGE = "일치하는 진영이 존재하지 않습니다."; + public static CampType divide(final char columnPosition) { if (Character.isLowerCase(columnPosition)) { return WHITE; @@ -11,6 +15,15 @@ public static CampType divide(final char columnPosition) { return BLACK; } + public static CampType from(final String name) { + return Arrays.stream(CampType.values()) + .filter(campType -> campType.name().equals(name)) + .findFirst() + .orElseThrow(() -> { + throw new IllegalArgumentException(ERROR_MESSAGE); + }); + } + public CampType changeTurn() { if (this == BLACK) { return WHITE; diff --git a/src/main/java/chess/domain/piece/PieceType.java b/src/main/java/chess/domain/piece/PieceType.java index dab6e4baddb..2bc1b8aef3b 100644 --- a/src/main/java/chess/domain/piece/PieceType.java +++ b/src/main/java/chess/domain/piece/PieceType.java @@ -1,5 +1,7 @@ package chess.domain.piece; +import java.util.Arrays; + public enum PieceType { QUEEN(Score.create(9)), ROOK(Score.create(5)), @@ -8,12 +10,23 @@ public enum PieceType { BISHOP(Score.create(3)), KING(Score.create(0)); + private static final String ERROR_MESSAGE = "일치하는 체스 말의 타입이 존재하지 않습니다."; + private final Score score; PieceType(final Score score) { this.score = score; } + public static PieceType from(final String name) { + return Arrays.stream(PieceType.values()) + .filter(pieceType -> pieceType.name().equals(name)) + .findFirst() + .orElseThrow(() -> { + throw new IllegalArgumentException(ERROR_MESSAGE); + }); + } + public Score getScore() { return score; } diff --git a/src/main/java/chess/entity/PieceEntity.java b/src/main/java/chess/entity/PieceEntity.java index 7b12b88413a..c823596b33a 100644 --- a/src/main/java/chess/entity/PieceEntity.java +++ b/src/main/java/chess/entity/PieceEntity.java @@ -30,4 +30,20 @@ public boolean equals(final Object o) { public int hashCode() { return Objects.hash(id, rank, file, pieceType, campType); } + + public Integer getRank() { + return rank; + } + + public Integer getFile() { + return file; + } + + public String getPieceType() { + return pieceType; + } + + public String getCampType() { + return campType; + } } diff --git a/src/main/java/chess/service/mapper/ChessBoardMapper.java b/src/main/java/chess/service/mapper/ChessBoardMapper.java new file mode 100644 index 00000000000..8fa586d5810 --- /dev/null +++ b/src/main/java/chess/service/mapper/ChessBoardMapper.java @@ -0,0 +1,27 @@ +package chess.service.mapper; + +import chess.domain.chess.CampType; +import chess.domain.piece.Movable; +import chess.domain.piece.Piece; +import chess.domain.piece.PieceType; +import chess.domain.piece.move.Position; +import chess.entity.PieceEntity; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public final class ChessBoardMapper { + + public static Map from(final List pieceEntities) { + final Map chessBoard = new HashMap<>(); + for (PieceEntity pieceEntity : pieceEntities) { + final Position position = new Position(pieceEntity.getRank(), pieceEntity.getFile()); + final PieceType pieceType = PieceType.from(pieceEntity.getPieceType()); + final CampType campType = CampType.from(pieceEntity.getCampType()); + final Movable movable = MovableMapper.from(pieceType); + chessBoard.put(position, new Piece(pieceType, campType, movable)); + } + return chessBoard; + } +} diff --git a/src/main/java/chess/service/mapper/MovableMapper.java b/src/main/java/chess/service/mapper/MovableMapper.java new file mode 100644 index 00000000000..b25b22fece1 --- /dev/null +++ b/src/main/java/chess/service/mapper/MovableMapper.java @@ -0,0 +1,31 @@ +package chess.service.mapper; + +import chess.domain.piece.Bishop; +import chess.domain.piece.King; +import chess.domain.piece.Knight; +import chess.domain.piece.Movable; +import chess.domain.piece.Pawn; +import chess.domain.piece.PieceType; +import chess.domain.piece.Queen; +import chess.domain.piece.Rook; + +public final class MovableMapper { + public static Movable from(final PieceType pieceType) { + if (pieceType == PieceType.QUEEN) { + return new Queen(); + } + if (pieceType == PieceType.ROOK) { + return new Rook(); + } + if (pieceType == PieceType.KNIGHT) { + return new Knight(); + } + if (pieceType == PieceType.PAWN) { + return new Pawn(); + } + if (pieceType == PieceType.BISHOP) { + return new Bishop(); + } + return new King(); + } +} From 9d2914b0cfa8b3e4c9cbb04312b0a3e9656f2592 Mon Sep 17 00:00:00 2001 From: jiwon Date: Sun, 26 Mar 2023 23:21:34 +0900 Subject: [PATCH 37/76] =?UTF-8?q?feat:=20=EC=B2=B4=EC=8A=A4=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=20=EC=95=84=EC=9D=B4=EB=94=94=EB=A5=BC=20=EA=B8=B0?= =?UTF-8?q?=EC=A4=80=EC=9C=BC=EB=A1=9C=20=EC=B2=B4=EC=8A=A4=ED=8C=90=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=9C?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 +++ .../java/chess/service/ChessBoardService.java | 23 ++++++++ .../java/chess/service/ChessBoardHelper.java | 58 +++++++++++++++++++ .../chess/service/ChessBoardServiceTest.java | 29 ++++++++++ 4 files changed, 118 insertions(+) create mode 100644 src/main/java/chess/service/ChessBoardService.java create mode 100644 src/test/java/chess/service/ChessBoardHelper.java create mode 100644 src/test/java/chess/service/ChessBoardServiceTest.java diff --git a/README.md b/README.md index 5f4a77c11a2..bd45de7a1b6 100644 --- a/README.md +++ b/README.md @@ -257,6 +257,14 @@ - [x] 사용자가 입력한 이름이 이미 존재한다면 해당 사용자의 아이디를, 아니라면 새롭게 삽입 후 생성된 아이디를 반환한다. - [x] 사용자의 이름을 바탕으로 사용자의 정보를 삽입한다. +### ChessGameService + +- [ ] 사용자 아이디를 기준으로 체스 게임 정보를 조회한다. + +### ChessBoardService + +- [x] 체스 게임 아이디를 기준으로 체스판 정보를 조회한다. + --- ## ✨domain - view diff --git a/src/main/java/chess/service/ChessBoardService.java b/src/main/java/chess/service/ChessBoardService.java new file mode 100644 index 00000000000..e6ccc5fb37c --- /dev/null +++ b/src/main/java/chess/service/ChessBoardService.java @@ -0,0 +1,23 @@ +package chess.service; + +import chess.dao.chess.PieceDao; +import chess.domain.piece.Piece; +import chess.domain.piece.move.Position; +import chess.entity.PieceEntity; +import chess.service.mapper.ChessBoardMapper; + +import java.util.List; +import java.util.Map; + +public class ChessBoardService { + private final PieceDao pieceDao; + + public ChessBoardService(final PieceDao pieceDao) { + this.pieceDao = pieceDao; + } + + public Map getByChessGameId(final Long chessGameId) { + final List pieceEntities = pieceDao.findByChessGameId(chessGameId); + return ChessBoardMapper.from(pieceEntities); + } +} diff --git a/src/test/java/chess/service/ChessBoardHelper.java b/src/test/java/chess/service/ChessBoardHelper.java new file mode 100644 index 00000000000..a291ab12931 --- /dev/null +++ b/src/test/java/chess/service/ChessBoardHelper.java @@ -0,0 +1,58 @@ +package chess.service; + +import chess.domain.chess.CampType; +import chess.domain.piece.Bishop; +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.move.Position; + +import java.util.HashMap; +import java.util.Map; + +import static chess.domain.piece.PieceType.BISHOP; +import static chess.domain.piece.PieceType.KING; +import static chess.domain.piece.PieceType.KNIGHT; +import static chess.domain.piece.PieceType.PAWN; +import static chess.domain.piece.PieceType.QUEEN; +import static chess.domain.piece.PieceType.ROOK; + +public final class ChessBoardHelper { + + public static Map createMockBoard() { + final Map board = new HashMap<>(); + createWhiteArea(board); + createBlackArea(board); + return board; + } + + private static void createWhiteArea(final Map board) { + createPieces(board, 0, CampType.WHITE); + createPawnPieces(board, 1, CampType.WHITE); + } + + private static void createBlackArea(final Map board) { + createPawnPieces(board, 6, CampType.BLACK); + createPieces(board, 7, CampType.BLACK); + } + + private static void createPieces(final Map board, final int rank, final CampType campType) { + board.put(new Position(rank, 0), new Piece(ROOK, campType, new Rook())); + board.put(new Position(rank, 1), new Piece(KNIGHT, campType, new Knight())); + board.put(new Position(rank, 2), new Piece(BISHOP, campType, new Bishop())); + board.put(new Position(rank, 3), new Piece(QUEEN, campType, new Queen())); + board.put(new Position(rank, 4), new Piece(KING, campType, new King())); + board.put(new Position(rank, 5), new Piece(BISHOP, campType, new Bishop())); + board.put(new Position(rank, 6), new Piece(KNIGHT, campType, new Knight())); + board.put(new Position(rank, 7), new Piece(ROOK, campType, new Rook())); + } + + private static void createPawnPieces(final Map board, final int rank, final CampType campType) { + for (int file = 0; file < 8; file++) { + board.put(new Position(rank, file), new Piece(PAWN, campType, new Pawn())); + } + } +} diff --git a/src/test/java/chess/service/ChessBoardServiceTest.java b/src/test/java/chess/service/ChessBoardServiceTest.java new file mode 100644 index 00000000000..7b6ba225248 --- /dev/null +++ b/src/test/java/chess/service/ChessBoardServiceTest.java @@ -0,0 +1,29 @@ +package chess.service; + +import chess.dao.chess.MockPieceDao; +import chess.domain.piece.Piece; +import chess.domain.piece.move.Position; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +class ChessBoardServiceTest { + + @Test + @DisplayName("체스 게임 아이디로 체스판 정보를 조회한다.") + void getByChessGameId() { + // given + final ChessBoardService chessBoardService = new ChessBoardService(new MockPieceDao()); + final Map expected = ChessBoardHelper.createMockBoard(); + + // when + final Map actual = chessBoardService.getByChessGameId(1L); + + // then + assertThat(actual) + .isEqualTo(expected); + } +} From 22d66a8f8c42070d18c9dd5012a8a1e2e6cceb5e Mon Sep 17 00:00:00 2001 From: jiwon Date: Sun, 26 Mar 2023 23:28:32 +0900 Subject: [PATCH 38/76] =?UTF-8?q?feat:=20=EC=B2=B4=EC=8A=A4=ED=8C=90=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=8B=9C=20ChessBoard=EB=A5=BC=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/chess/domain/board/ChessBoard.java | 18 ++++++++++++++++++ .../java/chess/service/ChessBoardService.java | 6 ++++-- .../chess/service/ChessBoardServiceTest.java | 9 +++------ 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/main/java/chess/domain/board/ChessBoard.java b/src/main/java/chess/domain/board/ChessBoard.java index 05607dfbebb..d9f4076d94a 100644 --- a/src/main/java/chess/domain/board/ChessBoard.java +++ b/src/main/java/chess/domain/board/ChessBoard.java @@ -7,6 +7,7 @@ import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; public final class ChessBoard { @@ -21,6 +22,10 @@ public static ChessBoard getInstance(final ChessGame chessGame) { return new ChessBoard(board); } + public static ChessBoard create(final Map board) { + return new ChessBoard(board); + } + public boolean contains(final Position position) { return board.containsKey(position); } @@ -72,6 +77,19 @@ private boolean isObstructed(final Position target, final Position unitPosition, return isObstructed(target, unitPosition, nextPosition); } + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final ChessBoard that = (ChessBoard) o; + return Objects.equals(board, that.board); + } + + @Override + public int hashCode() { + return Objects.hash(board); + } + public Map getBoard() { return Map.copyOf(board); } diff --git a/src/main/java/chess/service/ChessBoardService.java b/src/main/java/chess/service/ChessBoardService.java index e6ccc5fb37c..facb62ccc2f 100644 --- a/src/main/java/chess/service/ChessBoardService.java +++ b/src/main/java/chess/service/ChessBoardService.java @@ -1,6 +1,7 @@ package chess.service; import chess.dao.chess.PieceDao; +import chess.domain.board.ChessBoard; import chess.domain.piece.Piece; import chess.domain.piece.move.Position; import chess.entity.PieceEntity; @@ -16,8 +17,9 @@ public ChessBoardService(final PieceDao pieceDao) { this.pieceDao = pieceDao; } - public Map getByChessGameId(final Long chessGameId) { + public ChessBoard getByChessGameId(final Long chessGameId) { final List pieceEntities = pieceDao.findByChessGameId(chessGameId); - return ChessBoardMapper.from(pieceEntities); + final Map board = ChessBoardMapper.from(pieceEntities); + return ChessBoard.create(board); } } diff --git a/src/test/java/chess/service/ChessBoardServiceTest.java b/src/test/java/chess/service/ChessBoardServiceTest.java index 7b6ba225248..3e11df6214d 100644 --- a/src/test/java/chess/service/ChessBoardServiceTest.java +++ b/src/test/java/chess/service/ChessBoardServiceTest.java @@ -1,13 +1,10 @@ package chess.service; import chess.dao.chess.MockPieceDao; -import chess.domain.piece.Piece; -import chess.domain.piece.move.Position; +import chess.domain.board.ChessBoard; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.util.Map; - import static org.assertj.core.api.AssertionsForClassTypes.assertThat; class ChessBoardServiceTest { @@ -17,10 +14,10 @@ class ChessBoardServiceTest { void getByChessGameId() { // given final ChessBoardService chessBoardService = new ChessBoardService(new MockPieceDao()); - final Map expected = ChessBoardHelper.createMockBoard(); + final ChessBoard expected = ChessBoard.create(ChessBoardHelper.createMockBoard()); // when - final Map actual = chessBoardService.getByChessGameId(1L); + final ChessBoard actual = chessBoardService.getByChessGameId(1L); // then assertThat(actual) From 9707f956e440d8d80fa57855e6df41c321c3e5ba Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 00:04:13 +0900 Subject: [PATCH 39/76] =?UTF-8?q?feat:=20=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EC=9D=98=20=EC=95=84=EC=9D=B4=EB=94=94=EC=97=90=20=ED=95=B4?= =?UTF-8?q?=EB=8B=B9=ED=95=98=EB=8A=94=20=EC=B2=B4=EC=8A=A4=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=EC=9D=B4=20=EC=A1=B4=EC=9E=AC=ED=95=98=EB=A9=B4=20?= =?UTF-8?q?=ED=95=B4=EB=8B=B9=20=EA=B2=8C=EC=9E=84=EC=9D=84=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=ED=95=98=EA=B3=A0,=20=EC=95=84=EB=8B=88=EB=9D=BC?= =?UTF-8?q?=EB=A9=B4=20=EC=83=88=20=EA=B2=8C=EC=9E=84=EC=9D=84=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../java/chess/domain/chess/ChessGame.java | 19 ++++++++ .../java/chess/entity/ChessGameEntity.java | 8 ++++ src/main/java/chess/script/table.sql | 14 ++++++ .../java/chess/service/ChessGameService.java | 35 +++++++++++++++ .../chess/dao/chess/PieceDaoImplTest.java | 2 +- .../chess/dao/chess/PieceEntityHelper.java | 5 +-- .../java/chess/service/ChessBoardHelper.java | 36 ++++++++++++++- .../chess/service/ChessBoardServiceTest.java | 2 +- .../chess/service/ChessGameServiceTest.java | 45 +++++++++++++++++++ 10 files changed, 159 insertions(+), 9 deletions(-) create mode 100644 src/main/java/chess/service/ChessGameService.java create mode 100644 src/test/java/chess/service/ChessGameServiceTest.java diff --git a/README.md b/README.md index bd45de7a1b6..9f8601f496e 100644 --- a/README.md +++ b/README.md @@ -259,7 +259,7 @@ ### ChessGameService -- [ ] 사용자 아이디를 기준으로 체스 게임 정보를 조회한다. +- [x] 사용자의 아이디에 해당하는 체스 게임이 존재하면 해당 게임을 반환하고, 아니라면 새 게임을 반환한다. ### ChessBoardService diff --git a/src/main/java/chess/domain/chess/ChessGame.java b/src/main/java/chess/domain/chess/ChessGame.java index 5e787e6d530..93861a62d27 100644 --- a/src/main/java/chess/domain/chess/ChessGame.java +++ b/src/main/java/chess/domain/chess/ChessGame.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Map; +import java.util.Objects; public final class ChessGame { private static final int ALL_KING_ALIVE_COUNT = 2; @@ -17,6 +18,11 @@ public ChessGame() { this.chessBoard = ChessBoard.getInstance(this); } + public ChessGame(final ChessBoard chessBoard, final CampType currentCamp) { + this.chessBoard = chessBoard; + this.currentCamp = currentCamp; + } + public boolean run(final Position source, final Position target, final CampType currentCamp) { this.currentCamp = currentCamp; return play(source, target); @@ -95,6 +101,19 @@ private boolean isKingAlive() { return aliveKings.size() == ALL_KING_ALIVE_COUNT; } + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final ChessGame chessGame = (ChessGame) o; + return Objects.equals(chessBoard, chessGame.chessBoard) && currentCamp == chessGame.currentCamp; + } + + @Override + public int hashCode() { + return Objects.hash(chessBoard, currentCamp); + } + public Map getChessBoard() { return chessBoard.getBoard(); } diff --git a/src/main/java/chess/entity/ChessGameEntity.java b/src/main/java/chess/entity/ChessGameEntity.java index 0a7a75b874a..47d61ea07d2 100644 --- a/src/main/java/chess/entity/ChessGameEntity.java +++ b/src/main/java/chess/entity/ChessGameEntity.java @@ -25,4 +25,12 @@ public boolean equals(final Object o) { public int hashCode() { return Objects.hash(id, currentCamp, userId); } + + public Long getId() { + return id; + } + + public String getCurrentCamp() { + return currentCamp; + } } diff --git a/src/main/java/chess/script/table.sql b/src/main/java/chess/script/table.sql index 422c57774b8..af97e83dd2f 100644 --- a/src/main/java/chess/script/table.sql +++ b/src/main/java/chess/script/table.sql @@ -15,3 +15,17 @@ CREATE TABLE chess_game PRIMARY KEY (chess_game_id), FOREIGN KEY (user_id) REFERENCES user (user_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- piece +CREATE TABLE piece +( + piece_id BIGINT(20) NOT NULL AUTO_INCREMENT, + piece_rank INT NOT NULL, + piece_file INT NOT NULL, + piece_type VARCHAR(10) NOT NULL, + camp VARCHAR(5) NOT NULL, + chess_game_id BIGINT(20) NOT NULL, + PRIMARY KEY (piece_id), + FOREIGN KEY (chess_game_id) REFERENCES chess_game (chess_game_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + diff --git a/src/main/java/chess/service/ChessGameService.java b/src/main/java/chess/service/ChessGameService.java new file mode 100644 index 00000000000..c66b13a6dea --- /dev/null +++ b/src/main/java/chess/service/ChessGameService.java @@ -0,0 +1,35 @@ +package chess.service; + +import chess.dao.chess.ChessGameDao; +import chess.domain.board.ChessBoard; +import chess.domain.chess.CampType; +import chess.domain.chess.ChessGame; +import chess.entity.ChessGameEntity; + +import java.util.Optional; + +public final class ChessGameService { + private final ChessGameDao chessGameDao; + private final ChessBoardService chessBoardService; + + public ChessGameService(final ChessGameDao chessGameDao, final ChessBoardService chessBoardService) { + this.chessGameDao = chessGameDao; + this.chessBoardService = chessBoardService; + } + + public ChessGame getChessGame(final Long userId) { + final Optional findChessGameEntity = chessGameDao.findByUserId(userId); + if (findChessGameEntity.isEmpty()) { + return new ChessGame(); + } + final ChessGameEntity chessGameEntity = findChessGameEntity.get(); + final ChessBoard chessBoard = getChessBoard(chessGameEntity); + final String currentCamp = chessGameEntity.getCurrentCamp(); + return new ChessGame(chessBoard, CampType.from(currentCamp)); + } + + private ChessBoard getChessBoard(final ChessGameEntity chessGameEntity) { + final Long chessGameId = chessGameEntity.getId(); + return chessBoardService.getByChessGameId(chessGameId); + } +} diff --git a/src/test/java/chess/dao/chess/PieceDaoImplTest.java b/src/test/java/chess/dao/chess/PieceDaoImplTest.java index 25767a5e067..71ac199f6c2 100644 --- a/src/test/java/chess/dao/chess/PieceDaoImplTest.java +++ b/src/test/java/chess/dao/chess/PieceDaoImplTest.java @@ -23,6 +23,6 @@ void findByChessGameId() { .isEqualTo(PieceEntityHelper.createPieceEntities()); assertThat(pieceEntities.size()) - .isSameAs(32); + .isSameAs(18); } } diff --git a/src/test/java/chess/dao/chess/PieceEntityHelper.java b/src/test/java/chess/dao/chess/PieceEntityHelper.java index 5de93b0c811..0d330215584 100644 --- a/src/test/java/chess/dao/chess/PieceEntityHelper.java +++ b/src/test/java/chess/dao/chess/PieceEntityHelper.java @@ -23,15 +23,12 @@ private static List createMockPieces(final long id, final int rank, results.add(new PieceEntity(id + 2, rank, 2, "BISHOP", campType)); results.add(new PieceEntity(id + 3, rank, 3, "QUEEN", campType)); results.add(new PieceEntity(id + 4, rank, 4, "KING", campType)); - results.add(new PieceEntity(id + 5, rank, 5, "BISHOP", campType)); - results.add(new PieceEntity(id + 6, rank, 6, "KNIGHT", campType)); - results.add(new PieceEntity(id + 7, rank, 7, "ROOK", campType)); return results; } private static List createMockPawnPieces(final long id, final int rank, final String campType) { final List results = new ArrayList<>(); - for (int file = 0; file < 8; file++) { + for (int file = 0; file < 4; file++) { results.add(new PieceEntity(id + file, rank, file, "PAWN", campType)); } return results; diff --git a/src/test/java/chess/service/ChessBoardHelper.java b/src/test/java/chess/service/ChessBoardHelper.java index a291ab12931..e9c4d2c0773 100644 --- a/src/test/java/chess/service/ChessBoardHelper.java +++ b/src/test/java/chess/service/ChessBoardHelper.java @@ -1,5 +1,6 @@ package chess.service; +import chess.domain.board.ChessBoard; import chess.domain.chess.CampType; import chess.domain.piece.Bishop; import chess.domain.piece.King; @@ -22,11 +23,18 @@ public final class ChessBoardHelper { - public static Map createMockBoard() { + public static ChessBoard createMockBoard() { final Map board = new HashMap<>(); createWhiteArea(board); createBlackArea(board); - return board; + return ChessBoard.create(board); + } + + public static ChessBoard createMockProgressBoard() { + final Map board = new HashMap<>(); + createWhiteProgressArea(board); + createBlackProgressArea(board); + return ChessBoard.create(board); } private static void createWhiteArea(final Map board) { @@ -55,4 +63,28 @@ private static void createPawnPieces(final Map board, final int board.put(new Position(rank, file), new Piece(PAWN, campType, new Pawn())); } } + + private static void createWhiteProgressArea(final Map board) { + createProgressPieces(board, 0, CampType.WHITE); + createProgressPawnPieces(board, 1, CampType.WHITE); + } + + private static void createBlackProgressArea(final Map board) { + createProgressPawnPieces(board, 6, CampType.BLACK); + createProgressPieces(board, 7, CampType.BLACK); + } + + private static void createProgressPieces(final Map board, final int rank, final CampType campType) { + board.put(new Position(rank, 0), new Piece(ROOK, campType, new Rook())); + board.put(new Position(rank, 1), new Piece(KNIGHT, campType, new Knight())); + board.put(new Position(rank, 2), new Piece(BISHOP, campType, new Bishop())); + board.put(new Position(rank, 3), new Piece(QUEEN, campType, new Queen())); + board.put(new Position(rank, 4), new Piece(KING, campType, new King())); + } + + private static void createProgressPawnPieces(final Map board, final int rank, final CampType campType) { + for (int file = 0; file < 4; file++) { + board.put(new Position(rank, file), new Piece(PAWN, campType, new Pawn())); + } + } } diff --git a/src/test/java/chess/service/ChessBoardServiceTest.java b/src/test/java/chess/service/ChessBoardServiceTest.java index 3e11df6214d..446ee57e667 100644 --- a/src/test/java/chess/service/ChessBoardServiceTest.java +++ b/src/test/java/chess/service/ChessBoardServiceTest.java @@ -14,7 +14,7 @@ class ChessBoardServiceTest { void getByChessGameId() { // given final ChessBoardService chessBoardService = new ChessBoardService(new MockPieceDao()); - final ChessBoard expected = ChessBoard.create(ChessBoardHelper.createMockBoard()); + final ChessBoard expected = ChessBoardHelper.createMockBoard(); // when final ChessBoard actual = chessBoardService.getByChessGameId(1L); diff --git a/src/test/java/chess/service/ChessGameServiceTest.java b/src/test/java/chess/service/ChessGameServiceTest.java new file mode 100644 index 00000000000..0f4d6b20a6f --- /dev/null +++ b/src/test/java/chess/service/ChessGameServiceTest.java @@ -0,0 +1,45 @@ +package chess.service; + +import chess.dao.chess.MockChessGameDao; +import chess.dao.chess.MockPieceDao; +import chess.domain.chess.CampType; +import chess.domain.chess.ChessGame; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +class ChessGameServiceTest { + + @Test + @DisplayName("사용자의 아이디에 해당하는 체스 게임이 존재하지 않으면 새 게임을 반환한다.") + void getChessGame_empty() { + // given + final ChessGameService chessGameService = new ChessGameService( + new MockChessGameDao(), new ChessBoardService(new MockPieceDao())); + final ChessGame expected = new ChessGame(ChessBoardHelper.createMockBoard(), null); + + // when + final ChessGame actual = chessGameService.getChessGame(2L); + + // then + assertThat(actual) + .isEqualTo(expected); + } + + @Test + @DisplayName("사용자의 아이디에 해당하는 체스 게임이 존재하면 해당 게임을 반환한다.") + void getChessGame() { + // given + final ChessGameService chessGameService = new ChessGameService( + new MockChessGameDao(), new ChessBoardService(new MockPieceDao())); + final ChessGame expected = new ChessGame(ChessBoardHelper.createMockProgressBoard(), CampType.WHITE); + + // when + final ChessGame actual = chessGameService.getChessGame(1L); + + // then + assertThat(actual) + .isEqualTo(expected); + } +} From e394f3759b4b78b7dde8bdf0d7deba2553305302 Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 00:29:45 +0900 Subject: [PATCH 40/76] =?UTF-8?q?refactor:=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=20=EC=9D=B4=EB=A6=84=EC=9D=84=20=EB=B3=80=EA=B2=BD=ED=95=9C?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/service/UserService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/chess/service/UserService.java b/src/main/java/chess/service/UserService.java index 8e8e0c1a67b..d56bacf5e9a 100644 --- a/src/main/java/chess/service/UserService.java +++ b/src/main/java/chess/service/UserService.java @@ -20,10 +20,10 @@ public Long getUserId(final String name) { if (userEntity.isPresent()) { return userEntity.get().getId(); } - return insert(name); + return save(name); } - private Long insert(final String name) { + private Long save(final String name) { return userDao.insert(name); } } From 0eb3004049b2e652ab9cde757b487ca209ee73f8 Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 00:40:29 +0900 Subject: [PATCH 41/76] =?UTF-8?q?feat:=20=EC=9E=85=EB=A0=A5=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=93=A4=EC=96=B4=EC=98=A8=20=EC=B2=B4=EC=8A=A4=20?= =?UTF-8?q?=EA=B2=8C=EC=9E=84=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=B2=B4?= =?UTF-8?q?=EC=8A=A4=EB=A7=90=EC=9D=98=20=EC=A0=95=EB=B3=B4=EB=A5=BC=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 ++ src/main/java/chess/dao/chess/PieceDao.java | 2 ++ src/main/java/chess/dao/chess/PieceDaoImpl.java | 11 +++++++++++ src/main/java/chess/entity/PieceEntity.java | 9 ++++++++- src/test/java/chess/dao/chess/MockPieceDao.java | 5 +++++ .../java/chess/dao/chess/PieceDaoImplTest.java | 17 ++++++++++++++++- .../chess/service/ChessBoardServiceTest.java | 2 +- 7 files changed, 45 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9f8601f496e..3b21fa24f7f 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,8 @@ ### PieceDaoImpl - [x] 체스 게임 아이디를 기준으로 체스말 리스트의 정보를 조회한다. +- [x] 입력으로 들어온 체스 게임에 대한 체스말의 정보를 저장한다. +- [ ] 입력으로 들어온 체스 게임에 대해 특정 위치에 존재하는 체스말의 정보를 제거한다. --- diff --git a/src/main/java/chess/dao/chess/PieceDao.java b/src/main/java/chess/dao/chess/PieceDao.java index e9e50d2e71a..61a8f8b8e37 100644 --- a/src/main/java/chess/dao/chess/PieceDao.java +++ b/src/main/java/chess/dao/chess/PieceDao.java @@ -6,4 +6,6 @@ public interface PieceDao { List findByChessGameId(final Long chessGameId); + + Long save(final PieceEntity pieceEntity, final Long chessGameId); } diff --git a/src/main/java/chess/dao/chess/PieceDaoImpl.java b/src/main/java/chess/dao/chess/PieceDaoImpl.java index c53a3b99b8c..2d38c06b2e2 100644 --- a/src/main/java/chess/dao/chess/PieceDaoImpl.java +++ b/src/main/java/chess/dao/chess/PieceDaoImpl.java @@ -23,4 +23,15 @@ public List findByChessGameId(final Long chessGameId) { resultSet.getString("piece_type"), resultSet.getString("camp"))), String.valueOf(chessGameId)); } + + @Override + public Long save(final PieceEntity pieceEntity, final Long chessGameId) { + final String query = "INSERT INTO piece(piece_rank, piece_file, piece_type, camp, chess_game_id) " + + "VALUES (?, ?, ?, ?, ?)"; + return jdbcTemplate.executeUpdate(query, + String.valueOf(pieceEntity.getRank()), + String.valueOf(pieceEntity.getFile()), + pieceEntity.getPieceType(), pieceEntity.getCampType(), + String.valueOf(chessGameId)); + } } diff --git a/src/main/java/chess/entity/PieceEntity.java b/src/main/java/chess/entity/PieceEntity.java index c823596b33a..a4b7457267b 100644 --- a/src/main/java/chess/entity/PieceEntity.java +++ b/src/main/java/chess/entity/PieceEntity.java @@ -3,7 +3,7 @@ import java.util.Objects; public final class PieceEntity { - private final Long id; + private Long id; private final Integer rank; private final Integer file; private final String pieceType; @@ -18,6 +18,13 @@ public PieceEntity(final Long id, final Integer rank, final Integer file, this.campType = campType; } + public PieceEntity(final Integer rank, final Integer file, final String pieceType, final String campType) { + this.rank = rank; + this.file = file; + this.pieceType = pieceType; + this.campType = campType; + } + @Override public boolean equals(final Object o) { if (this == o) return true; diff --git a/src/test/java/chess/dao/chess/MockPieceDao.java b/src/test/java/chess/dao/chess/MockPieceDao.java index b86156be0e1..85f28aa318d 100644 --- a/src/test/java/chess/dao/chess/MockPieceDao.java +++ b/src/test/java/chess/dao/chess/MockPieceDao.java @@ -17,4 +17,9 @@ public MockPieceDao() { public List findByChessGameId(final Long chessGameId) { return List.copyOf(mockPieceEntites); } + + @Override + public Long save(final PieceEntity pieceEntity, final Long chessGameId) { + return 1L; + } } diff --git a/src/test/java/chess/dao/chess/PieceDaoImplTest.java b/src/test/java/chess/dao/chess/PieceDaoImplTest.java index 71ac199f6c2..5b4b827ea64 100644 --- a/src/test/java/chess/dao/chess/PieceDaoImplTest.java +++ b/src/test/java/chess/dao/chess/PieceDaoImplTest.java @@ -16,7 +16,7 @@ void findByChessGameId() { final PieceDao pieceDao = new MockPieceDao(); // when - List pieceEntities = pieceDao.findByChessGameId(1L); + final List pieceEntities = pieceDao.findByChessGameId(1L); // then assertThat(pieceEntities) @@ -25,4 +25,19 @@ void findByChessGameId() { assertThat(pieceEntities.size()) .isSameAs(18); } + + @Test + @DisplayName("체스 게임에 해당하는 체스말의 정보를 저장한다") + void save() { + // given + final PieceDao pieceDao = new MockPieceDao(); + + // when + final Long savedPieceId = pieceDao.save(new PieceEntity(1, 2, + "PAWN", "WHITE"), 1L); + + // then + assertThat(savedPieceId) + .isEqualTo(1L); + } } diff --git a/src/test/java/chess/service/ChessBoardServiceTest.java b/src/test/java/chess/service/ChessBoardServiceTest.java index 446ee57e667..71cc529924c 100644 --- a/src/test/java/chess/service/ChessBoardServiceTest.java +++ b/src/test/java/chess/service/ChessBoardServiceTest.java @@ -14,7 +14,7 @@ class ChessBoardServiceTest { void getByChessGameId() { // given final ChessBoardService chessBoardService = new ChessBoardService(new MockPieceDao()); - final ChessBoard expected = ChessBoardHelper.createMockBoard(); + final ChessBoard expected = ChessBoardHelper.createMockProgressBoard(); // when final ChessBoard actual = chessBoardService.getByChessGameId(1L); From 9f08e212c244655144b4d8ea60cf32005afda4ac Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 00:50:16 +0900 Subject: [PATCH 42/76] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EA=B0=80=20=ED=98=84=EC=9E=AC=20=EC=A7=84=ED=96=89=20=EC=A4=91?= =?UTF-8?q?=EC=9D=B8=20=EC=B2=B4=EC=8A=A4=20=EA=B2=8C=EC=9E=84=EC=9D=84=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + src/main/java/chess/dao/chess/ChessGameDao.java | 2 ++ .../java/chess/dao/chess/ChessGameDaoImpl.java | 9 +++++++++ src/main/java/chess/entity/ChessGameEntity.java | 11 ++++++++++- .../java/chess/dao/chess/ChessGameDaoImplTest.java | 14 ++++++++++++++ .../java/chess/dao/chess/MockChessGameDao.java | 5 +++++ 6 files changed, 41 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3b21fa24f7f..79126d2d284 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ ### ChessGameDaoImpl - [x] 사용자의 아이디를 기준으로 체스 게임을 조회한다. +- [x] 사용자가 현재 진행 중인 체스 게임을 저장한다. ### PieceDaoImpl diff --git a/src/main/java/chess/dao/chess/ChessGameDao.java b/src/main/java/chess/dao/chess/ChessGameDao.java index 8cecdd9abed..8130dcecf1c 100644 --- a/src/main/java/chess/dao/chess/ChessGameDao.java +++ b/src/main/java/chess/dao/chess/ChessGameDao.java @@ -6,4 +6,6 @@ public interface ChessGameDao { Optional findByUserId(final Long userId); + + Long save(final ChessGameEntity chessGameEntity); } diff --git a/src/main/java/chess/dao/chess/ChessGameDaoImpl.java b/src/main/java/chess/dao/chess/ChessGameDaoImpl.java index 646ff3d4fdf..e4e0aa32c17 100644 --- a/src/main/java/chess/dao/chess/ChessGameDaoImpl.java +++ b/src/main/java/chess/dao/chess/ChessGameDaoImpl.java @@ -21,4 +21,13 @@ public Optional findByUserId(final Long userId) { resultSet.getLong("user_id")) ), String.valueOf(userId)); } + + @Override + public Long save(final ChessGameEntity chessGameEntity) { + final String query = "INSERT INTO chess_game(current_camp, user_id) " + + "VALUES (?, ?)"; + return jdbcTemplate.executeUpdate(query, + chessGameEntity.getCurrentCamp(), + String.valueOf(chessGameEntity.getUserId())); + } } diff --git a/src/main/java/chess/entity/ChessGameEntity.java b/src/main/java/chess/entity/ChessGameEntity.java index 47d61ea07d2..00bd7628182 100644 --- a/src/main/java/chess/entity/ChessGameEntity.java +++ b/src/main/java/chess/entity/ChessGameEntity.java @@ -3,7 +3,7 @@ import java.util.Objects; public final class ChessGameEntity { - private final Long id; + private Long id; private final String currentCamp; private final Long userId; @@ -13,6 +13,11 @@ public ChessGameEntity(final Long id, final String currentCamp, final Long userI this.userId = userId; } + public ChessGameEntity(final String currentCamp, final Long userId) { + this.currentCamp = currentCamp; + this.userId = userId; + } + @Override public boolean equals(final Object o) { if (this == o) return true; @@ -33,4 +38,8 @@ public Long getId() { public String getCurrentCamp() { return currentCamp; } + + public Long getUserId() { + return userId; + } } diff --git a/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java b/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java index d0354afdced..cd324454868 100644 --- a/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java +++ b/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java @@ -41,4 +41,18 @@ void findByUserId_empty() { assertThat(chessGameEntity) .isEqualTo(Optional.empty()); } + + @Test + @DisplayName("사용자가 현재 진행 중인 체스 게임을 저장한다") + void save() { + // given + final ChessGameDao chessGameDao = new MockChessGameDao(); + + // when + final Long savedChessGameId = chessGameDao.save(new ChessGameEntity("WHITE", 1L)); + + // then + assertThat(savedChessGameId) + .isEqualTo(1L); + } } diff --git a/src/test/java/chess/dao/chess/MockChessGameDao.java b/src/test/java/chess/dao/chess/MockChessGameDao.java index dac0fd517f5..a69297a7bf2 100644 --- a/src/test/java/chess/dao/chess/MockChessGameDao.java +++ b/src/test/java/chess/dao/chess/MockChessGameDao.java @@ -12,4 +12,9 @@ public Optional findByUserId(final Long userId) { } return Optional.empty(); } + + @Override + public Long save(final ChessGameEntity chessGameEntity) { + return 1L; + } } From eca3a55d7427ab0cfc1fad3de64457914dff0d8b Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 01:33:58 +0900 Subject: [PATCH 43/76] =?UTF-8?q?test:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=EC=97=90=20=EB=8C=80=ED=95=9C=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EB=A1=9C=EC=A7=81=EC=9D=84=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/dao/user/UserDao.java | 2 +- src/main/java/chess/dao/user/UserDaoImpl.java | 2 +- src/main/java/chess/entity/UserEntity.java | 10 ++++++++- src/main/java/chess/service/UserService.java | 2 +- src/test/java/chess/dao/user/MockUserDao.java | 22 +++++++++++-------- .../java/chess/dao/user/UserDaoImplTest.java | 8 ++++--- .../java/chess/service/UserServiceTest.java | 2 +- 7 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/main/java/chess/dao/user/UserDao.java b/src/main/java/chess/dao/user/UserDao.java index baf77003884..7d4e7690cee 100644 --- a/src/main/java/chess/dao/user/UserDao.java +++ b/src/main/java/chess/dao/user/UserDao.java @@ -7,5 +7,5 @@ public interface UserDao { Optional findByName(final String name); - Long insert(final String name); + Long save(final String name); } diff --git a/src/main/java/chess/dao/user/UserDaoImpl.java b/src/main/java/chess/dao/user/UserDaoImpl.java index 89a5bb57fb0..3e66c839d05 100644 --- a/src/main/java/chess/dao/user/UserDaoImpl.java +++ b/src/main/java/chess/dao/user/UserDaoImpl.java @@ -23,7 +23,7 @@ public Optional findByName(final String name) { } @Override - public Long insert(final String name) { + public Long save(final String name) { final String query = "INSERT INTO user(user_name) VALUES(?)"; return jdbcTemplate.executeUpdate(query, name); } diff --git a/src/main/java/chess/entity/UserEntity.java b/src/main/java/chess/entity/UserEntity.java index abdc7ce6e66..d0bf9ca8243 100644 --- a/src/main/java/chess/entity/UserEntity.java +++ b/src/main/java/chess/entity/UserEntity.java @@ -3,7 +3,7 @@ import java.util.Objects; public final class UserEntity { - private final Long id; + private Long id; private final String name; public UserEntity(final Long id, final String name) { @@ -11,6 +11,10 @@ public UserEntity(final Long id, final String name) { this.name = name; } + public UserEntity(final String name) { + this.name = name; + } + @Override public boolean equals(final Object o) { if (this == o) return true; @@ -27,4 +31,8 @@ public int hashCode() { public Long getId() { return id; } + + public String getName() { + return name; + } } diff --git a/src/main/java/chess/service/UserService.java b/src/main/java/chess/service/UserService.java index d56bacf5e9a..6f67bf65667 100644 --- a/src/main/java/chess/service/UserService.java +++ b/src/main/java/chess/service/UserService.java @@ -24,6 +24,6 @@ public Long getUserId(final String name) { } private Long save(final String name) { - return userDao.insert(name); + return userDao.save(name); } } diff --git a/src/test/java/chess/dao/user/MockUserDao.java b/src/test/java/chess/dao/user/MockUserDao.java index 2afb22c58fa..903f38b1109 100644 --- a/src/test/java/chess/dao/user/MockUserDao.java +++ b/src/test/java/chess/dao/user/MockUserDao.java @@ -2,22 +2,26 @@ import chess.entity.UserEntity; +import java.util.Map; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; public class MockUserDao implements UserDao { + private static final Map STORAGE = new ConcurrentHashMap<>(); + private final AtomicLong pk = new AtomicLong(0L); + @Override public Optional findByName(final String name) { - if (name.equals("journey")) { - return Optional.of(new UserEntity(1L, "journey")); - } - return Optional.empty(); + return STORAGE.entrySet().stream() + .filter(entry -> entry.getValue().getName().equals(name)) + .map(entry -> new UserEntity(entry.getKey(), entry.getValue().getName())) + .findFirst(); } @Override - public Long insert(final String name) { - if (name.equals("journey")) { - return 1L; - } - return 2L; + public Long save(final String name) { + STORAGE.put(pk.addAndGet(1L), new UserEntity(name)); + return pk.longValue(); } } diff --git a/src/test/java/chess/dao/user/UserDaoImplTest.java b/src/test/java/chess/dao/user/UserDaoImplTest.java index 3bfc00e285b..72db22e6ab9 100644 --- a/src/test/java/chess/dao/user/UserDaoImplTest.java +++ b/src/test/java/chess/dao/user/UserDaoImplTest.java @@ -15,10 +15,12 @@ class UserDaoImplTest { void findByName() { // given final UserDao userDao = new MockUserDao(); - final UserEntity expected = new UserEntity(1L, "journey"); + final String name = "journey"; + userDao.save(name); + final UserEntity expected = new UserEntity(1L, name); // when - final Optional userEntity = userDao.findByName("journey"); + final Optional userEntity = userDao.findByName(name); final UserEntity actual = userEntity.get(); // then @@ -46,7 +48,7 @@ void insert() { final UserDao userDao = new MockUserDao(); // when - Long userId = userDao.insert("journey"); + Long userId = userDao.save("journey"); // then assertThat(userId) diff --git a/src/test/java/chess/service/UserServiceTest.java b/src/test/java/chess/service/UserServiceTest.java index 8b66fcaf735..1b81a5e13bc 100644 --- a/src/test/java/chess/service/UserServiceTest.java +++ b/src/test/java/chess/service/UserServiceTest.java @@ -33,6 +33,6 @@ void getUserId_new() { // then assertThat(userId) - .isEqualTo(2L); + .isEqualTo(1L); } } From 33a1f832209dc242cf39ebf22d186381e38c6827 Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 01:35:32 +0900 Subject: [PATCH 44/76] =?UTF-8?q?test:=20=EC=B2=B4=EC=8A=A4=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=EC=97=90=20=EB=8C=80=ED=95=9C=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=A1=9C=EC=A7=81=EC=9D=84=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chess/dao/chess/ChessGameDaoImplTest.java | 1 + .../java/chess/dao/chess/MockChessGameDao.java | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java b/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java index cd324454868..646d66c9789 100644 --- a/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java +++ b/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java @@ -16,6 +16,7 @@ void findByUserId() { // given final ChessGameDao chessGameDao = new MockChessGameDao(); final ChessGameEntity expected = new ChessGameEntity(1L, "WHITE", 1L); + chessGameDao.save(expected); final long userId = 1L; // when diff --git a/src/test/java/chess/dao/chess/MockChessGameDao.java b/src/test/java/chess/dao/chess/MockChessGameDao.java index a69297a7bf2..78dd5988e47 100644 --- a/src/test/java/chess/dao/chess/MockChessGameDao.java +++ b/src/test/java/chess/dao/chess/MockChessGameDao.java @@ -2,19 +2,27 @@ import chess.entity.ChessGameEntity; +import java.util.Map; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; public class MockChessGameDao implements ChessGameDao { + private static final Map STORAGE = new ConcurrentHashMap<>(); + private final AtomicLong pk = new AtomicLong(0L); + @Override public Optional findByUserId(final Long userId) { - if (userId == 1L) { - return Optional.of(new ChessGameEntity(1L, "WHITE", 1L)); - } - return Optional.empty(); + return STORAGE.entrySet().stream() + .filter(entry -> entry.getValue().getUserId().equals(userId)) + .map(entry -> new ChessGameEntity(entry.getKey(), + entry.getValue().getCurrentCamp(), entry.getValue().getUserId())) + .findFirst(); } @Override public Long save(final ChessGameEntity chessGameEntity) { - return 1L; + STORAGE.put(pk.addAndGet(1L), chessGameEntity); + return pk.longValue(); } } From 4649903c67bcfb986dcbae888940d983b7c629f0 Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 02:36:17 +0900 Subject: [PATCH 45/76] =?UTF-8?q?feat:=20=EC=9E=85=EB=A0=A5=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=93=A4=EC=96=B4=EC=98=A8=20=EC=B2=B4=EC=8A=A4=20?= =?UTF-8?q?=EA=B2=8C=EC=9E=84=EC=97=90=20=EB=8C=80=ED=95=B4=20=ED=8A=B9?= =?UTF-8?q?=EC=A0=95=20=EC=9C=84=EC=B9=98=EC=97=90=20=EC=A1=B4=EC=9E=AC?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EC=B2=B4=EC=8A=A4=EB=A7=90=EC=9D=98=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=EB=A5=BC=20=EC=A0=9C=EA=B1=B0=ED=95=9C?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/chess/dao/chess/PieceDao.java | 4 +- .../java/chess/dao/chess/PieceDaoImpl.java | 40 ++++++++++++++++-- src/main/java/chess/entity/PieceEntity.java | 35 ++++++++++++---- .../chess/dao/chess/MockChessGameDao.java | 4 +- .../java/chess/dao/chess/MockPieceDao.java | 42 +++++++++++++++---- .../chess/dao/chess/PieceDaoImplTest.java | 35 +++++++++++++--- .../chess/dao/chess/PieceEntityHelper.java | 27 ++++++------ src/test/java/chess/dao/user/MockUserDao.java | 2 +- .../chess/service/ChessBoardServiceTest.java | 10 ++++- .../chess/service/ChessGameServiceTest.java | 23 ++++++++-- 11 files changed, 176 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 79126d2d284..b9544a76104 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ - [x] 체스 게임 아이디를 기준으로 체스말 리스트의 정보를 조회한다. - [x] 입력으로 들어온 체스 게임에 대한 체스말의 정보를 저장한다. -- [ ] 입력으로 들어온 체스 게임에 대해 특정 위치에 존재하는 체스말의 정보를 제거한다. +- [x] 입력으로 들어온 체스 게임에 대해 특정 위치에 존재하는 체스말의 정보를 제거한다. --- diff --git a/src/main/java/chess/dao/chess/PieceDao.java b/src/main/java/chess/dao/chess/PieceDao.java index 61a8f8b8e37..903cc2393f3 100644 --- a/src/main/java/chess/dao/chess/PieceDao.java +++ b/src/main/java/chess/dao/chess/PieceDao.java @@ -7,5 +7,7 @@ public interface PieceDao { List findByChessGameId(final Long chessGameId); - Long save(final PieceEntity pieceEntity, final Long chessGameId); + Long save(final PieceEntity pieceEntity); + + void deleteByPositions(final Long chessGameId, final PieceEntity... pieceEntity); } diff --git a/src/main/java/chess/dao/chess/PieceDaoImpl.java b/src/main/java/chess/dao/chess/PieceDaoImpl.java index 2d38c06b2e2..a8869f0b068 100644 --- a/src/main/java/chess/dao/chess/PieceDaoImpl.java +++ b/src/main/java/chess/dao/chess/PieceDaoImpl.java @@ -16,7 +16,7 @@ public PieceDaoImpl(final JdbcTemplate jdbcTemplate) { @Override public List findByChessGameId(final Long chessGameId) { final String query = "SELECT * FROM piece WHERE chess_game_id = ?"; - return jdbcTemplate.findAll(query, (resultSet -> new PieceEntity( + return jdbcTemplate.findAll(query, (resultSet -> PieceEntity.createWithId( resultSet.getLong("piece_id"), resultSet.getInt("piece_rank"), resultSet.getInt("piece_file"), @@ -25,13 +25,47 @@ public List findByChessGameId(final Long chessGameId) { } @Override - public Long save(final PieceEntity pieceEntity, final Long chessGameId) { + public Long save(final PieceEntity pieceEntity) { final String query = "INSERT INTO piece(piece_rank, piece_file, piece_type, camp, chess_game_id) " + "VALUES (?, ?, ?, ?, ?)"; return jdbcTemplate.executeUpdate(query, String.valueOf(pieceEntity.getRank()), String.valueOf(pieceEntity.getFile()), pieceEntity.getPieceType(), pieceEntity.getCampType(), - String.valueOf(chessGameId)); + String.valueOf(pieceEntity.getChessGameId())); + } + + @Override + public void deleteByPositions(final Long chessGameId, final PieceEntity... pieceEntity) { + if (pieceEntity.length == 1) { + deleteOneByPosition(chessGameId, pieceEntity[0]); + } + final PieceEntity source = pieceEntity[0]; + final PieceEntity destination = pieceEntity[1]; + deleteTwoByPosition(chessGameId, source, destination); + } + + private void deleteOneByPosition(final Long chessGameId, final PieceEntity pieceEntity) { + final String query = "DELETE FROM piece WHERE chess_game_id = ? " + + "and piece_rank = ? and piece_file = ?"; + + jdbcTemplate.executeUpdate(query, + String.valueOf(chessGameId), + String.valueOf(pieceEntity.getRank()), + String.valueOf(pieceEntity.getFile())); + } + + private void deleteTwoByPosition(final Long chessGameId, final PieceEntity source, final PieceEntity destination) { + final String query = "DELETE FROM piece WHERE chess_game_id = ? " + + "and (" + + " (piece_rank = ? and piece_file = ?) or (piece_rank = ? and piece_file = ?)" + + ")"; + + jdbcTemplate.executeUpdate(query, + String.valueOf(chessGameId), + String.valueOf(source.getRank()), + String.valueOf(source.getFile()), + String.valueOf(destination.getRank()), + String.valueOf(destination.getFile())); } } diff --git a/src/main/java/chess/entity/PieceEntity.java b/src/main/java/chess/entity/PieceEntity.java index a4b7457267b..d5093eed19b 100644 --- a/src/main/java/chess/entity/PieceEntity.java +++ b/src/main/java/chess/entity/PieceEntity.java @@ -4,27 +4,32 @@ public final class PieceEntity { private Long id; + private Long chessGameId; private final Integer rank; private final Integer file; private final String pieceType; private final String campType; - public PieceEntity(final Long id, final Integer rank, final Integer file, - final String pieceType, final String campType) { + private PieceEntity(final Long id, final Long chessGameId, final Integer rank, + final Integer file, final String pieceType, final String campType) { this.id = id; + this.chessGameId = chessGameId; this.rank = rank; this.file = file; this.pieceType = pieceType; this.campType = campType; } - public PieceEntity(final Integer rank, final Integer file, final String pieceType, final String campType) { - this.rank = rank; - this.file = file; - this.pieceType = pieceType; - this.campType = campType; + public static PieceEntity createWithId(final Long id, final Integer rank, final Integer file, + final String pieceType, final String campType) { + return new PieceEntity(id, null, rank, file, pieceType, campType); } + public static PieceEntity createWithChessGameId(final Long chessGameId, final Integer rank, final Integer file, + final String pieceType, final String campType) { + return new PieceEntity(null, chessGameId, rank, file, pieceType, campType); + } + @Override public boolean equals(final Object o) { if (this == o) return true; @@ -38,6 +43,18 @@ public int hashCode() { return Objects.hash(id, rank, file, pieceType, campType); } + @Override + public String toString() { + return "PieceEntity{" + + "id=" + id + + ", chessGameId=" + chessGameId + + ", rank=" + rank + + ", file=" + file + + ", pieceType='" + pieceType + '\'' + + ", campType='" + campType + '\'' + + '}'; + } + public Integer getRank() { return rank; } @@ -53,4 +70,8 @@ public String getPieceType() { public String getCampType() { return campType; } + + public Long getChessGameId() { + return chessGameId; + } } diff --git a/src/test/java/chess/dao/chess/MockChessGameDao.java b/src/test/java/chess/dao/chess/MockChessGameDao.java index 78dd5988e47..aca03aa4f12 100644 --- a/src/test/java/chess/dao/chess/MockChessGameDao.java +++ b/src/test/java/chess/dao/chess/MockChessGameDao.java @@ -8,9 +8,9 @@ import java.util.concurrent.atomic.AtomicLong; public class MockChessGameDao implements ChessGameDao { - private static final Map STORAGE = new ConcurrentHashMap<>(); + private final Map STORAGE = new ConcurrentHashMap<>(); private final AtomicLong pk = new AtomicLong(0L); - + @Override public Optional findByUserId(final Long userId) { return STORAGE.entrySet().stream() diff --git a/src/test/java/chess/dao/chess/MockPieceDao.java b/src/test/java/chess/dao/chess/MockPieceDao.java index 85f28aa318d..3ce4ab7ef5e 100644 --- a/src/test/java/chess/dao/chess/MockPieceDao.java +++ b/src/test/java/chess/dao/chess/MockPieceDao.java @@ -3,23 +3,47 @@ import chess.entity.PieceEntity; import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; public class MockPieceDao implements PieceDao { + private final Map STORAGE = new ConcurrentHashMap<>(); + private final AtomicLong pk = new AtomicLong(0L); - private final List mockPieceEntites; - - public MockPieceDao() { - this.mockPieceEntites = PieceEntityHelper.createPieceEntities(); - + @Override + public List findByChessGameId(final Long chessGameId) { + return STORAGE.values().stream() + .filter(pieceEntity -> pieceEntity.getChessGameId().equals(chessGameId)) + .map(pieceEntity -> PieceEntity.createWithChessGameId(pieceEntity.getChessGameId(), pieceEntity.getRank(), + pieceEntity.getFile(), pieceEntity.getPieceType(), pieceEntity.getCampType())) + .collect(Collectors.toUnmodifiableList()); } @Override - public List findByChessGameId(final Long chessGameId) { - return List.copyOf(mockPieceEntites); + public Long save(final PieceEntity pieceEntity) { + STORAGE.put(pk.addAndGet(1L), pieceEntity); + return pk.longValue(); } @Override - public Long save(final PieceEntity pieceEntity, final Long chessGameId) { - return 1L; + public void deleteByPositions(final Long chessGameId, final PieceEntity... pieceEntity) { + delete(pieceEntity[0]); + if (pieceEntity.length == 2) { + delete(pieceEntity[1]); + } + } + + private void delete(final PieceEntity pieceEntity) { + STORAGE.entrySet().stream() + .filter(entry -> isSamePosition(entry.getValue(), pieceEntity)) + .forEach(entry -> STORAGE.remove(entry.getKey())); + } + + private boolean isSamePosition(final PieceEntity value, final PieceEntity other) { + return Objects.equals(value.getRank(), other.getRank()) + && Objects.equals(value.getFile(), other.getFile()); } } diff --git a/src/test/java/chess/dao/chess/PieceDaoImplTest.java b/src/test/java/chess/dao/chess/PieceDaoImplTest.java index 5b4b827ea64..def71a2ecec 100644 --- a/src/test/java/chess/dao/chess/PieceDaoImplTest.java +++ b/src/test/java/chess/dao/chess/PieceDaoImplTest.java @@ -4,6 +4,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.Collections; import java.util.List; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -14,15 +15,18 @@ public class PieceDaoImplTest { void findByChessGameId() { // given final PieceDao pieceDao = new MockPieceDao(); + final long chessGameId = 1L; + final List pieceEntities = PieceEntityHelper.createPieceEntities(chessGameId); + pieceEntities.forEach(pieceDao::save); // when - final List pieceEntities = pieceDao.findByChessGameId(1L); + final List findChessEntities = pieceDao.findByChessGameId(chessGameId); // then - assertThat(pieceEntities) - .isEqualTo(PieceEntityHelper.createPieceEntities()); + assertThat(findChessEntities) + .isEqualTo(PieceEntityHelper.createPieceEntities(chessGameId)); - assertThat(pieceEntities.size()) + assertThat(findChessEntities.size()) .isSameAs(18); } @@ -33,11 +37,30 @@ void save() { final PieceDao pieceDao = new MockPieceDao(); // when - final Long savedPieceId = pieceDao.save(new PieceEntity(1, 2, - "PAWN", "WHITE"), 1L); + final Long savedPieceId = pieceDao.save(PieceEntity.createWithChessGameId(1L, 1, 2, + "PAWN", "WHITE")); // then assertThat(savedPieceId) .isEqualTo(1L); } + + @Test + @DisplayName("입력으로 들어온 체스 게임에 대해 특정 위치에 존재하는 체스말의 정보를 제거한다") + void deleteByPositions() { + // given + final PieceDao pieceDao = new MockPieceDao(); + final long chessGameId = 1L; + final PieceEntity entity1 = PieceEntity.createWithChessGameId(chessGameId, 1, 1, "PAWN", "WHITE"); + final PieceEntity entity2 = PieceEntity.createWithChessGameId(chessGameId, 1, 1, "PAWN", "WHITE"); + pieceDao.save(entity1); + pieceDao.save(entity2); + + // when + pieceDao.deleteByPositions(chessGameId, entity1, entity2); + + // then + assertThat(pieceDao.findByChessGameId(1L)) + .isEqualTo(Collections.emptyList()); + } } diff --git a/src/test/java/chess/dao/chess/PieceEntityHelper.java b/src/test/java/chess/dao/chess/PieceEntityHelper.java index 0d330215584..b86b849ac74 100644 --- a/src/test/java/chess/dao/chess/PieceEntityHelper.java +++ b/src/test/java/chess/dao/chess/PieceEntityHelper.java @@ -7,29 +7,30 @@ public class PieceEntityHelper { - public static List createPieceEntities() { + public static List createPieceEntities(final Long chessGameId) { final List results = new ArrayList<>(); - results.addAll(createMockPieces(1L, 0, "WHITE")); - results.addAll(createMockPawnPieces(9L, 1, "WHITE")); - results.addAll(createMockPawnPieces(17L, 6, "BLACK")); - results.addAll(createMockPieces(25L, 7, "BLACK")); + results.addAll(createMockPieces(chessGameId, 0, "WHITE")); + results.addAll(createMockPawnPieces(chessGameId, 1, "WHITE")); + results.addAll(createMockPawnPieces(chessGameId, 6, "BLACK")); + results.addAll(createMockPieces(chessGameId, 7, "BLACK")); return results; } - private static List createMockPieces(final long id, final int rank, final String campType) { + private static List createMockPieces(final long chessGameId, final int rank, + final String campType) { final List results = new ArrayList<>(); - results.add(new PieceEntity(id, rank, 0, "ROOK", campType)); - results.add(new PieceEntity(id + 1, rank, 1, "KNIGHT", campType)); - results.add(new PieceEntity(id + 2, rank, 2, "BISHOP", campType)); - results.add(new PieceEntity(id + 3, rank, 3, "QUEEN", campType)); - results.add(new PieceEntity(id + 4, rank, 4, "KING", campType)); + results.add(PieceEntity.createWithChessGameId(chessGameId, rank, 0, "ROOK", campType)); + results.add(PieceEntity.createWithChessGameId(chessGameId, rank, 1, "KNIGHT", campType)); + results.add(PieceEntity.createWithChessGameId(chessGameId, rank, 2, "BISHOP", campType)); + results.add(PieceEntity.createWithChessGameId(chessGameId, rank, 3, "QUEEN", campType)); + results.add(PieceEntity.createWithChessGameId(chessGameId, rank, 4, "KING", campType)); return results; } - private static List createMockPawnPieces(final long id, final int rank, final String campType) { + private static List createMockPawnPieces(final long chessGameId, final int rank, final String campType) { final List results = new ArrayList<>(); for (int file = 0; file < 4; file++) { - results.add(new PieceEntity(id + file, rank, file, "PAWN", campType)); + results.add(PieceEntity.createWithChessGameId(chessGameId, rank, file, "PAWN", campType)); } return results; } diff --git a/src/test/java/chess/dao/user/MockUserDao.java b/src/test/java/chess/dao/user/MockUserDao.java index 903f38b1109..7a3f07430f4 100644 --- a/src/test/java/chess/dao/user/MockUserDao.java +++ b/src/test/java/chess/dao/user/MockUserDao.java @@ -8,7 +8,7 @@ import java.util.concurrent.atomic.AtomicLong; public class MockUserDao implements UserDao { - private static final Map STORAGE = new ConcurrentHashMap<>(); + private final Map STORAGE = new ConcurrentHashMap<>(); private final AtomicLong pk = new AtomicLong(0L); @Override diff --git a/src/test/java/chess/service/ChessBoardServiceTest.java b/src/test/java/chess/service/ChessBoardServiceTest.java index 71cc529924c..4940421625a 100644 --- a/src/test/java/chess/service/ChessBoardServiceTest.java +++ b/src/test/java/chess/service/ChessBoardServiceTest.java @@ -1,10 +1,15 @@ package chess.service; import chess.dao.chess.MockPieceDao; +import chess.dao.chess.PieceDao; +import chess.dao.chess.PieceEntityHelper; import chess.domain.board.ChessBoard; +import chess.entity.PieceEntity; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.List; + import static org.assertj.core.api.AssertionsForClassTypes.assertThat; class ChessBoardServiceTest { @@ -13,7 +18,10 @@ class ChessBoardServiceTest { @DisplayName("체스 게임 아이디로 체스판 정보를 조회한다.") void getByChessGameId() { // given - final ChessBoardService chessBoardService = new ChessBoardService(new MockPieceDao()); + final PieceDao pieceDao = new MockPieceDao(); + final List pieceEntities = PieceEntityHelper.createPieceEntities(1L); + pieceEntities.forEach(pieceDao::save); + final ChessBoardService chessBoardService = new ChessBoardService(pieceDao); final ChessBoard expected = ChessBoardHelper.createMockProgressBoard(); // when diff --git a/src/test/java/chess/service/ChessGameServiceTest.java b/src/test/java/chess/service/ChessGameServiceTest.java index 0f4d6b20a6f..ac5e8e7be3e 100644 --- a/src/test/java/chess/service/ChessGameServiceTest.java +++ b/src/test/java/chess/service/ChessGameServiceTest.java @@ -2,11 +2,17 @@ import chess.dao.chess.MockChessGameDao; import chess.dao.chess.MockPieceDao; +import chess.dao.chess.PieceEntityHelper; +import chess.domain.board.ChessBoard; import chess.domain.chess.CampType; import chess.domain.chess.ChessGame; +import chess.entity.ChessGameEntity; +import chess.entity.PieceEntity; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.List; + import static org.assertj.core.api.AssertionsForClassTypes.assertThat; class ChessGameServiceTest { @@ -31,12 +37,21 @@ void getChessGame_empty() { @DisplayName("사용자의 아이디에 해당하는 체스 게임이 존재하면 해당 게임을 반환한다.") void getChessGame() { // given - final ChessGameService chessGameService = new ChessGameService( - new MockChessGameDao(), new ChessBoardService(new MockPieceDao())); - final ChessGame expected = new ChessGame(ChessBoardHelper.createMockProgressBoard(), CampType.WHITE); + final Long userId = 1L; + final Long chessGameId = 1L; + final List pieceEntities = PieceEntityHelper.createPieceEntities(chessGameId); + final MockPieceDao pieceDao = new MockPieceDao(); + pieceEntities.forEach(pieceDao::save); + + final MockChessGameDao chessGameDao = new MockChessGameDao(); + chessGameDao.save(new ChessGameEntity("WHITE", userId)); + + final ChessGameService chessGameService = new ChessGameService(chessGameDao, new ChessBoardService(pieceDao)); + final ChessBoard mockProgressBoard = ChessBoardHelper.createMockProgressBoard(); + final ChessGame expected = new ChessGame(mockProgressBoard, CampType.WHITE); // when - final ChessGame actual = chessGameService.getChessGame(1L); + final ChessGame actual = chessGameService.getChessGame(userId); // then assertThat(actual) From 36dfe4263fef2d0e1677165476c01c81a21c546b Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 15:03:07 +0900 Subject: [PATCH 46/76] =?UTF-8?q?feat:=20=EC=B2=B4=EC=8A=A4=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=20=EC=95=84=EC=9D=B4=EB=94=94=EC=97=90=20=ED=95=B4?= =?UTF-8?q?=EB=8B=B9=ED=95=98=EB=8A=94=20=EC=B2=B4=EC=8A=A4=EB=A7=90=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=EB=A5=BC=20=EC=A0=9C=EA=B1=B0=ED=95=9C?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/chess/dao/chess/PieceDao.java | 2 ++ .../java/chess/dao/chess/PieceDaoImpl.java | 8 ++++++++ .../java/chess/dao/chess/MockPieceDao.java | 7 +++++++ .../chess/dao/chess/PieceDaoImplTest.java | 19 +++++++++++++++++++ 5 files changed, 37 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b9544a76104..837606ee633 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,7 @@ - [x] 체스 게임 아이디를 기준으로 체스말 리스트의 정보를 조회한다. - [x] 입력으로 들어온 체스 게임에 대한 체스말의 정보를 저장한다. - [x] 입력으로 들어온 체스 게임에 대해 특정 위치에 존재하는 체스말의 정보를 제거한다. +- [x] 체스 게임 아이디에 해당하는 체스말 정보를 제거한다 --- @@ -280,7 +281,6 @@ - [x] 게임 안내 메시지를 출력한다. - [x] 체스판에 있는 체스말을 출력하고, 비어있는 곳은 .으로 출력한다. -- source에 있는 말이 target으로 이동된 체스판을 출력한다. - [x] 각 진영의 점수와 이긴 진영에 대해서 출력한다. ### PieceName diff --git a/src/main/java/chess/dao/chess/PieceDao.java b/src/main/java/chess/dao/chess/PieceDao.java index 903cc2393f3..45b1ec12533 100644 --- a/src/main/java/chess/dao/chess/PieceDao.java +++ b/src/main/java/chess/dao/chess/PieceDao.java @@ -10,4 +10,6 @@ public interface PieceDao { Long save(final PieceEntity pieceEntity); void deleteByPositions(final Long chessGameId, final PieceEntity... pieceEntity); + + void deleteByChessGameId(Long chessGameId); } diff --git a/src/main/java/chess/dao/chess/PieceDaoImpl.java b/src/main/java/chess/dao/chess/PieceDaoImpl.java index a8869f0b068..ba1a7317361 100644 --- a/src/main/java/chess/dao/chess/PieceDaoImpl.java +++ b/src/main/java/chess/dao/chess/PieceDaoImpl.java @@ -45,6 +45,14 @@ public void deleteByPositions(final Long chessGameId, final PieceEntity... piece deleteTwoByPosition(chessGameId, source, destination); } + @Override + public void deleteByChessGameId(final Long chessGameId) { + final String query = "DELETE FROM piece where chess_game_id = ?"; + + jdbcTemplate.executeUpdate(query, + String.valueOf(chessGameId)); + } + private void deleteOneByPosition(final Long chessGameId, final PieceEntity pieceEntity) { final String query = "DELETE FROM piece WHERE chess_game_id = ? " + "and piece_rank = ? and piece_file = ?"; diff --git a/src/test/java/chess/dao/chess/MockPieceDao.java b/src/test/java/chess/dao/chess/MockPieceDao.java index 3ce4ab7ef5e..541b62c4c5c 100644 --- a/src/test/java/chess/dao/chess/MockPieceDao.java +++ b/src/test/java/chess/dao/chess/MockPieceDao.java @@ -36,6 +36,13 @@ public void deleteByPositions(final Long chessGameId, final PieceEntity... piece } } + @Override + public void deleteByChessGameId(final Long chessGameId) { + STORAGE.keySet().stream() + .filter(key -> Objects.equals(STORAGE.get(key).getChessGameId(), chessGameId)) + .forEach(STORAGE::remove); + } + private void delete(final PieceEntity pieceEntity) { STORAGE.entrySet().stream() .filter(entry -> isSamePosition(entry.getValue(), pieceEntity)) diff --git a/src/test/java/chess/dao/chess/PieceDaoImplTest.java b/src/test/java/chess/dao/chess/PieceDaoImplTest.java index def71a2ecec..b1f1fd200d9 100644 --- a/src/test/java/chess/dao/chess/PieceDaoImplTest.java +++ b/src/test/java/chess/dao/chess/PieceDaoImplTest.java @@ -63,4 +63,23 @@ void deleteByPositions() { assertThat(pieceDao.findByChessGameId(1L)) .isEqualTo(Collections.emptyList()); } + + @Test + @DisplayName("체스 게임 아이디에 해당하는 체스말 정보를 제거한다") + void deleteByChessGameId() { + // given + final PieceDao pieceDao = new MockPieceDao(); + final long chessGameId = 1L; + final PieceEntity entity1 = PieceEntity.createWithChessGameId(chessGameId, 1, 1, "PAWN", "WHITE"); + final PieceEntity entity2 = PieceEntity.createWithChessGameId(chessGameId, 1, 1, "PAWN", "WHITE"); + pieceDao.save(entity1); + pieceDao.save(entity2); + + // when + pieceDao.deleteByChessGameId(chessGameId); + + // then + assertThat(pieceDao.findByChessGameId(1L)) + .isEqualTo(Collections.emptyList()); + } } From 0a6c3f21f1c4efca84243e631978cb01c1f309ce Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 15:09:31 +0900 Subject: [PATCH 47/76] =?UTF-8?q?feat:=20=EC=B2=B4=EC=8A=A4=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=20=EC=95=84=EC=9D=B4=EB=94=94=EC=97=90=20=ED=95=B4?= =?UTF-8?q?=EB=8B=B9=ED=95=98=EB=8A=94=20=EA=B2=8C=EC=9E=84=EC=9D=98=20?= =?UTF-8?q?=ED=98=84=EC=9E=AC=20=EC=A7=84=EC=98=81=EC=9D=84=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + .../java/chess/dao/chess/ChessGameDao.java | 3 +++ .../java/chess/dao/chess/ChessGameDaoImpl.java | 15 +++++++++++++-- .../chess/dao/chess/ChessGameDaoImplTest.java | 18 ++++++++++++++++++ .../java/chess/dao/chess/MockChessGameDao.java | 15 +++++++++++---- 5 files changed, 46 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 837606ee633..b15b9bf91ac 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ - [x] 사용자의 아이디를 기준으로 체스 게임을 조회한다. - [x] 사용자가 현재 진행 중인 체스 게임을 저장한다. +- [x] 체스 게임 아이디에 해당하는 게임의 현재 진영을 업데이트한다. ### PieceDaoImpl diff --git a/src/main/java/chess/dao/chess/ChessGameDao.java b/src/main/java/chess/dao/chess/ChessGameDao.java index 8130dcecf1c..46bd10ecac6 100644 --- a/src/main/java/chess/dao/chess/ChessGameDao.java +++ b/src/main/java/chess/dao/chess/ChessGameDao.java @@ -1,5 +1,6 @@ package chess.dao.chess; +import chess.domain.chess.CampType; import chess.entity.ChessGameEntity; import java.util.Optional; @@ -8,4 +9,6 @@ public interface ChessGameDao { Optional findByUserId(final Long userId); Long save(final ChessGameEntity chessGameEntity); + + void updateCurrentCampById(Long id, CampType currentCamp); } diff --git a/src/main/java/chess/dao/chess/ChessGameDaoImpl.java b/src/main/java/chess/dao/chess/ChessGameDaoImpl.java index e4e0aa32c17..d7d92f7449f 100644 --- a/src/main/java/chess/dao/chess/ChessGameDaoImpl.java +++ b/src/main/java/chess/dao/chess/ChessGameDaoImpl.java @@ -1,6 +1,7 @@ package chess.dao.chess; import chess.database.JdbcTemplate; +import chess.domain.chess.CampType; import chess.entity.ChessGameEntity; import java.util.Optional; @@ -15,6 +16,7 @@ public ChessGameDaoImpl(final JdbcTemplate jdbcTemplate) { @Override public Optional findByUserId(final Long userId) { final String query = "SELECT * FROM chess_game WHERE user_id = ?"; + return jdbcTemplate.findOne(query, (resultSet -> new ChessGameEntity( resultSet.getLong("chess_game_id"), resultSet.getString("current_camp"), @@ -24,10 +26,19 @@ public Optional findByUserId(final Long userId) { @Override public Long save(final ChessGameEntity chessGameEntity) { - final String query = "INSERT INTO chess_game(current_camp, user_id) " + - "VALUES (?, ?)"; + final String query = "INSERT INTO chess_game(current_camp, user_id) VALUES (?, ?)"; + return jdbcTemplate.executeUpdate(query, chessGameEntity.getCurrentCamp(), String.valueOf(chessGameEntity.getUserId())); } + + @Override + public void updateCurrentCampById(final Long id, final CampType currentCamp) { + final String query = "UPDATE chess_game SET current_camp = ? WHERE chess_game_id = ?"; + + jdbcTemplate.executeUpdate(query, + currentCamp.name(), + String.valueOf(id)); + } } diff --git a/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java b/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java index 646d66c9789..74fd204f6dd 100644 --- a/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java +++ b/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java @@ -1,5 +1,6 @@ package chess.dao.chess; +import chess.domain.chess.CampType; import chess.entity.ChessGameEntity; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -56,4 +57,21 @@ void save() { assertThat(savedChessGameId) .isEqualTo(1L); } + + @Test + @DisplayName("체스 게임 아이디에 해당하는 게임의 현재 진영을 업데이트한다") + void updateCurrentCampById() { + // given + final ChessGameDao chessGameDao = new MockChessGameDao(); + final Long savedChessGameId = chessGameDao.save(new ChessGameEntity("WHITE", 1L)); + final Optional expected = Optional.of(new ChessGameEntity("BLACK", 1L)); + + // when + chessGameDao.updateCurrentCampById(savedChessGameId, CampType.BLACK); + + // then + final Optional actual = chessGameDao.findByUserId(1L); + assertThat(actual) + .isEqualTo(expected); + } } diff --git a/src/test/java/chess/dao/chess/MockChessGameDao.java b/src/test/java/chess/dao/chess/MockChessGameDao.java index aca03aa4f12..7c6c8b60ab4 100644 --- a/src/test/java/chess/dao/chess/MockChessGameDao.java +++ b/src/test/java/chess/dao/chess/MockChessGameDao.java @@ -1,5 +1,6 @@ package chess.dao.chess; +import chess.domain.chess.CampType; import chess.entity.ChessGameEntity; import java.util.Map; @@ -13,10 +14,10 @@ public class MockChessGameDao implements ChessGameDao { @Override public Optional findByUserId(final Long userId) { - return STORAGE.entrySet().stream() - .filter(entry -> entry.getValue().getUserId().equals(userId)) - .map(entry -> new ChessGameEntity(entry.getKey(), - entry.getValue().getCurrentCamp(), entry.getValue().getUserId())) + return STORAGE.values().stream() + .filter(chessGameEntity -> chessGameEntity.getUserId().equals(userId)) + .map(chessGameEntity -> new ChessGameEntity(chessGameEntity.getId(), chessGameEntity.getCurrentCamp(), + chessGameEntity.getUserId())) .findFirst(); } @@ -25,4 +26,10 @@ public Long save(final ChessGameEntity chessGameEntity) { STORAGE.put(pk.addAndGet(1L), chessGameEntity); return pk.longValue(); } + + @Override + public void updateCurrentCampById(final Long id, final CampType currentCamp) { + final ChessGameEntity chessGameEntity = STORAGE.get(id); + STORAGE.put(id, new ChessGameEntity(currentCamp.name(), chessGameEntity.getUserId())); + } } From 2e98cfac4785eefb0affd0523e191815a351d098 Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 15:09:52 +0900 Subject: [PATCH 48/76] =?UTF-8?q?test:=20mapper=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=A5=BC=20=EC=88=98=EC=A0=95=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/chess/controller/mapper/PieceDtoMapperTest.java | 3 +-- .../java/chess/controller/mapper/PositionDtoMapperTest.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/test/java/chess/controller/mapper/PieceDtoMapperTest.java b/src/test/java/chess/controller/mapper/PieceDtoMapperTest.java index da82ff9dbae..73f7746b9e8 100644 --- a/src/test/java/chess/controller/mapper/PieceDtoMapperTest.java +++ b/src/test/java/chess/controller/mapper/PieceDtoMapperTest.java @@ -17,11 +17,10 @@ class PieceDtoMapperTest { @DisplayName("체스말 정보가 주어지면, 체스말에 대한 dto를 생성한다.") void createPieceDto() { // given - final PieceDtoMapper pieceDtoMapper = new PieceDtoMapper(); final Piece piece = new Piece(PieceType.ROOK, CampType.WHITE, new Rook()); // when, then - final PieceDto pieceDto = assertDoesNotThrow(() -> pieceDtoMapper.createPieceDto(piece)); + final PieceDto pieceDto = assertDoesNotThrow(() -> PieceDtoMapper.createPieceDto(piece)); assertThat(pieceDto) .isInstanceOf(PieceDto.class); } diff --git a/src/test/java/chess/controller/mapper/PositionDtoMapperTest.java b/src/test/java/chess/controller/mapper/PositionDtoMapperTest.java index 318ffd1b9c4..b56e8be0e4d 100644 --- a/src/test/java/chess/controller/mapper/PositionDtoMapperTest.java +++ b/src/test/java/chess/controller/mapper/PositionDtoMapperTest.java @@ -13,12 +13,11 @@ class PositionDtoMapperTest { @DisplayName("rank, file이 주어지면 위치에 대한 dto를 생성한다.") void createPositionDto() { // given - final PositionDtoMapper positionDtoMapper = new PositionDtoMapper(); final int rank = 3; final int file = 3; // when, then - final PositionDto positionDto = assertDoesNotThrow(() -> positionDtoMapper.createPositionDto(rank, file)); + final PositionDto positionDto = assertDoesNotThrow(() -> PositionDtoMapper.createPositionDto(rank, file)); assertThat(positionDto) .isInstanceOf(PositionDto.class); } From 04fb202f04ddbfce8c17045b9b2f0dc85e7a8f32 Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 15:11:53 +0900 Subject: [PATCH 49/76] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EC=9D=98=20=EC=95=84=EC=9D=B4=EB=94=94=EC=97=90=20=ED=95=B4?= =?UTF-8?q?=EB=8B=B9=ED=95=98=EB=8A=94=20=EC=B2=B4=EC=8A=A4=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=EC=9D=84=20=EC=A0=9C=EA=B1=B0=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + src/main/java/chess/dao/chess/ChessGameDao.java | 2 ++ .../java/chess/dao/chess/ChessGameDaoImpl.java | 8 ++++++++ .../chess/dao/chess/ChessGameDaoImplTest.java | 16 ++++++++++++++++ .../java/chess/dao/chess/MockChessGameDao.java | 8 ++++++++ 5 files changed, 35 insertions(+) diff --git a/README.md b/README.md index b15b9bf91ac..22998217efd 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ - [x] 사용자의 아이디를 기준으로 체스 게임을 조회한다. - [x] 사용자가 현재 진행 중인 체스 게임을 저장한다. - [x] 체스 게임 아이디에 해당하는 게임의 현재 진영을 업데이트한다. +- [x] 사용자의 아이디에 해당하는 체스 게임을 제거한다. ### PieceDaoImpl diff --git a/src/main/java/chess/dao/chess/ChessGameDao.java b/src/main/java/chess/dao/chess/ChessGameDao.java index 46bd10ecac6..dcc7881d763 100644 --- a/src/main/java/chess/dao/chess/ChessGameDao.java +++ b/src/main/java/chess/dao/chess/ChessGameDao.java @@ -11,4 +11,6 @@ public interface ChessGameDao { Long save(final ChessGameEntity chessGameEntity); void updateCurrentCampById(Long id, CampType currentCamp); + + void deleteByUserId(Long userId); } diff --git a/src/main/java/chess/dao/chess/ChessGameDaoImpl.java b/src/main/java/chess/dao/chess/ChessGameDaoImpl.java index d7d92f7449f..dbb756fb506 100644 --- a/src/main/java/chess/dao/chess/ChessGameDaoImpl.java +++ b/src/main/java/chess/dao/chess/ChessGameDaoImpl.java @@ -41,4 +41,12 @@ public void updateCurrentCampById(final Long id, final CampType currentCamp) { currentCamp.name(), String.valueOf(id)); } + + @Override + public void deleteByUserId(final Long userId) { + final String query = "DELETE FROM chess_game where user_id = ?"; + + jdbcTemplate.executeUpdate(query, + String.valueOf(userId)); + } } diff --git a/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java b/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java index 74fd204f6dd..1f8e3bb8ca7 100644 --- a/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java +++ b/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java @@ -74,4 +74,20 @@ void updateCurrentCampById() { assertThat(actual) .isEqualTo(expected); } + + @Test + @DisplayName("사용자의 아이디에 해당하는 체스 게임을 제거한다") + void deleteByUserId() { + // given + final ChessGameDao chessGameDao = new MockChessGameDao(); + chessGameDao.save(new ChessGameEntity("WHITE", 1L)); + + // when + chessGameDao.deleteByUserId(1L); + + // then + final Optional actual = chessGameDao.findByUserId(1L); + assertThat(actual) + .isEqualTo(Optional.empty()); + } } diff --git a/src/test/java/chess/dao/chess/MockChessGameDao.java b/src/test/java/chess/dao/chess/MockChessGameDao.java index 7c6c8b60ab4..a5edec77d14 100644 --- a/src/test/java/chess/dao/chess/MockChessGameDao.java +++ b/src/test/java/chess/dao/chess/MockChessGameDao.java @@ -4,6 +4,7 @@ import chess.entity.ChessGameEntity; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; @@ -32,4 +33,11 @@ public void updateCurrentCampById(final Long id, final CampType currentCamp) { final ChessGameEntity chessGameEntity = STORAGE.get(id); STORAGE.put(id, new ChessGameEntity(currentCamp.name(), chessGameEntity.getUserId())); } + + @Override + public void deleteByUserId(final Long userId) { + STORAGE.keySet().stream() + .filter(key -> Objects.equals(STORAGE.get(key).getUserId(), userId)) + .forEach(STORAGE::remove); + } } From a56e8ab8e3988b76a8ba28887ef8df2a32f3ecdd Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 15:30:31 +0900 Subject: [PATCH 50/76] =?UTF-8?q?feat:=20chessGame=EC=9D=98=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EC=9E=90=EC=97=90=EC=84=9C=20=EC=A7=84=EC=98=81?= =?UTF-8?q?=EC=9D=84=20=EB=B0=9B=EC=95=84=EC=98=AC=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/chess/domain/chess/ChessGame.java | 26 +++++++------- .../mapper/ChessBoardDtoMapperTest.java | 3 +- .../chess/domain/board/ChessBoardTest.java | 16 ++++----- .../domain/chess/ChessGameCalculatorTest.java | 2 +- .../chess/domain/chess/ChessGameHelper.java | 34 +++++++++---------- .../chess/domain/chess/ChessGameTest.java | 15 ++++---- 6 files changed, 49 insertions(+), 47 deletions(-) diff --git a/src/main/java/chess/domain/chess/ChessGame.java b/src/main/java/chess/domain/chess/ChessGame.java index 93861a62d27..b498c6fac4f 100644 --- a/src/main/java/chess/domain/chess/ChessGame.java +++ b/src/main/java/chess/domain/chess/ChessGame.java @@ -14,7 +14,8 @@ public final class ChessGame { private final ChessBoard chessBoard; private CampType currentCamp; - public ChessGame() { + public ChessGame(final CampType currentCamp) { + this.currentCamp = currentCamp; this.chessBoard = ChessBoard.getInstance(this); } @@ -23,11 +24,6 @@ public ChessGame(final ChessBoard chessBoard, final CampType currentCamp) { this.currentCamp = currentCamp; } - public boolean run(final Position source, final Position target, final CampType currentCamp) { - this.currentCamp = currentCamp; - return play(source, target); - } - public Map getWhiteBoard() { return chessBoard.getBoardByCamp(CampType.WHITE); } @@ -36,7 +32,7 @@ public Map getBlackBoard() { return chessBoard.getBoardByCamp(CampType.BLACK); } - private boolean play(final Position source, final Position target) { + public void play(final Position source, final Position target) { validateCamp(source); validateTargetSameCamp(target); validateObstacle(source, target); @@ -44,7 +40,12 @@ private boolean play(final Position source, final Position target) { throw new IllegalArgumentException("이동할 수 없는 위치입니다."); } movePiece(source, target); - return isKingAlive(); + currentCamp = currentCamp.changeTurn(); + } + + public boolean isKingAlive() { + List aliveKings = chessBoard.getAliveKings(); + return aliveKings.size() == ALL_KING_ALIVE_COUNT; } private void validateObstacle(final Position source, final Position target) { @@ -96,11 +97,6 @@ private void validatePieceExistence(final Position position) { } } - private boolean isKingAlive() { - List aliveKings = chessBoard.getAliveKings(); - return aliveKings.size() == ALL_KING_ALIVE_COUNT; - } - @Override public boolean equals(final Object o) { if (this == o) return true; @@ -117,4 +113,8 @@ public int hashCode() { public Map getChessBoard() { return chessBoard.getBoard(); } + + public CampType getCurrentCamp() { + return currentCamp; + } } diff --git a/src/test/java/chess/controller/mapper/ChessBoardDtoMapperTest.java b/src/test/java/chess/controller/mapper/ChessBoardDtoMapperTest.java index 7a332054500..18bb8d63666 100644 --- a/src/test/java/chess/controller/mapper/ChessBoardDtoMapperTest.java +++ b/src/test/java/chess/controller/mapper/ChessBoardDtoMapperTest.java @@ -1,6 +1,7 @@ package chess.controller.mapper; import chess.controller.dto.ChessBoardDto; +import chess.domain.chess.CampType; import chess.domain.chess.ChessGame; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -14,7 +15,7 @@ class ChessBoardDtoMapperTest { @DisplayName("체스판 정보가 주어지면, 체스판 dto를 생성한다.") void createChessBoardDto() { // given - final ChessGame chessGame = new ChessGame(); + final ChessGame chessGame = new ChessGame(CampType.WHITE); // when, then final ChessBoardDto chessBoardDto = assertDoesNotThrow(() -> diff --git a/src/test/java/chess/domain/board/ChessBoardTest.java b/src/test/java/chess/domain/board/ChessBoardTest.java index fb49559fddd..564260ae040 100644 --- a/src/test/java/chess/domain/board/ChessBoardTest.java +++ b/src/test/java/chess/domain/board/ChessBoardTest.java @@ -24,7 +24,7 @@ class ChessBoardTest { @DisplayName("체스판을 생성하고, 체스판 말의 수가 32개인지 확인한다.") void create() { // given - final ChessBoard chessBoard = ChessBoard.getInstance(new ChessGame()); + final ChessBoard chessBoard = ChessBoard.getInstance(new ChessGame(CampType.WHITE)); // when final Map board = chessBoard.getBoard(); @@ -38,7 +38,7 @@ void create() { @CsvSource(value = {"0:0:true", "3:5:false"}, delimiter = ':') void contains(final int rank, final int file, final boolean expected) { // given - final ChessBoard chessBoard = ChessBoard.getInstance(new ChessGame()); + final ChessBoard chessBoard = ChessBoard.getInstance(new ChessGame(CampType.WHITE)); // when, then assertThat(chessBoard.contains(new Position(rank, file))) @@ -49,7 +49,7 @@ void contains(final int rank, final int file, final boolean expected) { @DisplayName("특정 위치에 존재하는 체스말을 반환한다.") void getPiece() { // given - final ChessBoard chessBoard = ChessBoard.getInstance(new ChessGame()); + final ChessBoard chessBoard = ChessBoard.getInstance(new ChessGame(CampType.WHITE)); // when, then assertThat(chessBoard.getPiece(new Position(0, 0))) @@ -60,7 +60,7 @@ void getPiece() { @DisplayName("입력받은 위치에 존재하는 체스말을 제거한다.") void removePiece() { // given - final ChessBoard chessBoard = ChessBoard.getInstance(new ChessGame()); + final ChessBoard chessBoard = ChessBoard.getInstance(new ChessGame(CampType.WHITE)); final Position removePosition = new Position(1, 0); // when @@ -75,7 +75,7 @@ void removePiece() { @DisplayName("입력받은 위치에 체스말을 둔다.") void putPiece() { // given - final ChessBoard chessBoard = ChessBoard.getInstance(new ChessGame()); + final ChessBoard chessBoard = ChessBoard.getInstance(new ChessGame(CampType.WHITE)); final Position putPosition = new Position(2, 0); final Piece piece = new Piece(PieceType.PAWN, CampType.WHITE, new Pawn()); @@ -91,7 +91,7 @@ void putPiece() { @CsvSource(value = {"1:3:false", "3:6:true"}, delimiter = ':') void isPossibleRoute(final int rank, final int file, final boolean expected) { // given - final ChessBoard chessBoard = ChessBoard.getInstance(new ChessGame()); + final ChessBoard chessBoard = ChessBoard.getInstance(new ChessGame(CampType.WHITE)); final Position source = new Position(0, 3); final Position target = new Position(rank, file); @@ -110,7 +110,7 @@ void isPossibleRoute(final int rank, final int file, final boolean expected) { @DisplayName("현재 체스판에서 살아있는 킹들을 조회한다.") void getAliveKings() { // given - final ChessBoard chessBoard = ChessBoard.getInstance(new ChessGame()); + final ChessBoard chessBoard = ChessBoard.getInstance(new ChessGame(CampType.WHITE)); // when List aliveKings = chessBoard.getAliveKings(); @@ -129,7 +129,7 @@ void getAliveKings() { @DisplayName("입력받은 진영의 체스판을 반환한다.") void getBoardByCamp() { // given - final ChessBoard chessBoard = ChessBoard.getInstance(new ChessGame()); + final ChessBoard chessBoard = ChessBoard.getInstance(new ChessGame(CampType.WHITE)); // when final Map whiteBoard = chessBoard.getBoardByCamp(CampType.WHITE); diff --git a/src/test/java/chess/domain/chess/ChessGameCalculatorTest.java b/src/test/java/chess/domain/chess/ChessGameCalculatorTest.java index 949d2da9ea0..b6f89ef17bc 100644 --- a/src/test/java/chess/domain/chess/ChessGameCalculatorTest.java +++ b/src/test/java/chess/domain/chess/ChessGameCalculatorTest.java @@ -13,7 +13,7 @@ class ChessGameCalculatorTest { @DisplayName("현재 체스판의 각 진영에 대한 점수를 계산한다.") void calculate() { // given - final ChessGame chessGame = new ChessGame(); + final ChessGame chessGame = new ChessGame(CampType.WHITE); final ScoreVO expected = new ScoreVO(Score.create(38.0), Score.create(38.0)); // when diff --git a/src/test/java/chess/domain/chess/ChessGameHelper.java b/src/test/java/chess/domain/chess/ChessGameHelper.java index bc04c023147..e36ad34a3ed 100644 --- a/src/test/java/chess/domain/chess/ChessGameHelper.java +++ b/src/test/java/chess/domain/chess/ChessGameHelper.java @@ -3,22 +3,22 @@ import chess.domain.piece.move.Position; public class ChessGameHelper { - public static boolean playKingDie(final ChessGame chessGame) { - chessGame.run(new Position(7, 1), new Position(5, 0), CampType.BLACK); - chessGame.run(new Position(3, 0), new Position(4, 0), CampType.WHITE); - chessGame.run(new Position(6, 1), new Position(5, 1), CampType.BLACK); - chessGame.run(new Position(4, 0), new Position(5, 1), CampType.WHITE); - chessGame.run(new Position(6, 2), new Position(5, 2), CampType.BLACK); - chessGame.run(new Position(0, 0), new Position(5, 0), CampType.WHITE); - chessGame.run(new Position(5, 2), new Position(4, 2), CampType.BLACK); - chessGame.run(new Position(1, 3), new Position(3, 3), CampType.WHITE); - chessGame.run(new Position(6, 4), new Position(4, 4), CampType.BLACK); - chessGame.run(new Position(0, 2), new Position(5, 7), CampType.WHITE); - chessGame.run(new Position(7, 3), new Position(3, 7), CampType.BLACK); - chessGame.run(new Position(0, 6), new Position(2, 5), CampType.WHITE); - chessGame.run(new Position(7, 4), new Position(6, 4), CampType.BLACK); - chessGame.run(new Position(3, 3), new Position(4, 3), CampType.WHITE); - chessGame.run(new Position(6, 4), new Position(5, 4), CampType.BLACK); - return chessGame.run(new Position(4, 3), new Position(5, 4), CampType.WHITE); + public static void playKingDie(final ChessGame chessGame) { + chessGame.play(new Position(7, 1), new Position(5, 0)); + chessGame.play(new Position(3, 0), new Position(4, 0)); + chessGame.play(new Position(6, 1), new Position(5, 1)); + chessGame.play(new Position(4, 0), new Position(5, 1)); + chessGame.play(new Position(6, 2), new Position(5, 2)); + chessGame.play(new Position(0, 0), new Position(5, 0)); + chessGame.play(new Position(5, 2), new Position(4, 2)); + chessGame.play(new Position(1, 3), new Position(3, 3)); + chessGame.play(new Position(6, 4), new Position(4, 4)); + chessGame.play(new Position(0, 2), new Position(5, 7)); + chessGame.play(new Position(7, 3), new Position(3, 7)); + chessGame.play(new Position(0, 6), new Position(2, 5)); + chessGame.play(new Position(7, 4), new Position(6, 4)); + chessGame.play(new Position(3, 3), new Position(4, 3)); + chessGame.play(new Position(6, 4), new Position(5, 4)); + chessGame.play(new Position(4, 3), new Position(5, 4)); } } diff --git a/src/test/java/chess/domain/chess/ChessGameTest.java b/src/test/java/chess/domain/chess/ChessGameTest.java index 0148c5eccdd..16283632c77 100644 --- a/src/test/java/chess/domain/chess/ChessGameTest.java +++ b/src/test/java/chess/domain/chess/ChessGameTest.java @@ -18,12 +18,12 @@ class ChessGameTest { @CsvSource(value = {"6:6"}, delimiter = ':') void playMovableFail(final int rank, final int file) { // given - final ChessGame chessGame = new ChessGame(); + final ChessGame chessGame = new ChessGame(CampType.WHITE); final Position source = new Position(rank, file); final Position target = new Position(6, 7); // when, then - assertThatThrownBy(() -> chessGame.run(source, target, CampType.WHITE)) + assertThatThrownBy(() -> chessGame.play(source, target)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("현재 차례가 아닙니다. 현재 차례 = WHITE"); } @@ -32,13 +32,14 @@ void playMovableFail(final int rank, final int file) { @DisplayName("모든 진영의 왕이 살아있는 것이 아니라면 false를 반환한다.") void run() { // given - final ChessGame chessGame = new ChessGame(); + final ChessGame chessGame = new ChessGame(CampType.WHITE); final Position source = new Position(1, 0); final Position target = new Position(3, 0); // when - chessGame.run(source, target, CampType.WHITE); - boolean isGameRun = ChessGameHelper.playKingDie(chessGame); + chessGame.play(source, target); + ChessGameHelper.playKingDie(chessGame); + final boolean isGameRun = chessGame.isKingAlive(); // then assertThat(isGameRun) @@ -49,7 +50,7 @@ void run() { @DisplayName("WHITE 진영의 체스판을 반환한다.") void getWhiteBoard() { // given - final ChessGame chessGame = new ChessGame(); + final ChessGame chessGame = new ChessGame(CampType.WHITE); // when final Map whiteBoard = chessGame.getWhiteBoard(); @@ -63,7 +64,7 @@ void getWhiteBoard() { @DisplayName("BLACK 진영의 체스판을 반환한다.") void getBlackBoard() { // given - final ChessGame chessGame = new ChessGame(); + final ChessGame chessGame = new ChessGame(CampType.WHITE); // when final Map blackBoard = chessGame.getBlackBoard(); From 6f0113350d554f54eea7fa9612eb1ff7fb70dbcd Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 15:31:20 +0900 Subject: [PATCH 51/76] =?UTF-8?q?fix:=20delete=20=EC=97=B0=EC=82=B0=20?= =?UTF-8?q?=EC=8B=9C=20key=EB=A5=BC=20=EB=B0=9B=EC=95=84=EC=98=A4=EC=A7=80?= =?UTF-8?q?=20=EC=95=8A=EB=8A=94=20=EA=B2=83=EC=9D=84=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=B4=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D=20=EB=A1=9C=EC=A7=81=EC=9D=84=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/database/JdbcTemplate.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/chess/database/JdbcTemplate.java b/src/main/java/chess/database/JdbcTemplate.java index daf8c47c1ba..3bdf2373881 100644 --- a/src/main/java/chess/database/JdbcTemplate.java +++ b/src/main/java/chess/database/JdbcTemplate.java @@ -74,7 +74,7 @@ public Long executeUpdate(final String query, final ResultSet generatedKeys = preparedStatement.getGeneratedKeys(); if (!generatedKeys.next()) { - throw new SQLException("Update Exception! - generated key error."); + return null; } return generatedKeys.getLong(1); } catch (SQLException e) { From 7ad0aa617c07ebe9d05bb3e63d122d6a0a5009fd Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 15:43:14 +0900 Subject: [PATCH 52/76] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EC=9D=98=20=EC=95=84=EC=9D=B4=EB=94=94=EB=A5=BC=20=EA=B8=B0?= =?UTF-8?q?=EC=A4=80=EC=9C=BC=EB=A1=9C=20=EC=B2=B4=EC=8A=A4=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=EC=9D=84=20=EC=A1=B0=ED=9A=8C=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + .../java/chess/service/ChessGameService.java | 22 +++++++++- .../chess/dao/chess/MockChessGameDao.java | 5 ++- .../chess/service/ChessGameServiceTest.java | 44 ++++++++++++++----- 4 files changed, 59 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 22998217efd..762309db469 100644 --- a/README.md +++ b/README.md @@ -266,6 +266,7 @@ ### ChessGameService - [x] 사용자의 아이디에 해당하는 체스 게임이 존재하면 해당 게임을 반환하고, 아니라면 새 게임을 반환한다. +- [x] 사용자의 아이디를 기준으로 체스 게임을 조회한다. ### ChessBoardService diff --git a/src/main/java/chess/service/ChessGameService.java b/src/main/java/chess/service/ChessGameService.java index c66b13a6dea..14221404c97 100644 --- a/src/main/java/chess/service/ChessGameService.java +++ b/src/main/java/chess/service/ChessGameService.java @@ -20,9 +20,29 @@ public ChessGameService(final ChessGameDao chessGameDao, final ChessBoardService public ChessGame getChessGame(final Long userId) { final Optional findChessGameEntity = chessGameDao.findByUserId(userId); if (findChessGameEntity.isEmpty()) { - return new ChessGame(); + return getNewChessGame(userId); } final ChessGameEntity chessGameEntity = findChessGameEntity.get(); + return getExistChessGame(chessGameEntity); + } + + public Long getChessGameId(final Long userId) { + final Optional findChessGameEntity = chessGameDao.findByUserId(userId); + if (findChessGameEntity.isEmpty()) { + throw new IllegalArgumentException("저장된 데이터가 존재하지 않습니다."); + } + return findChessGameEntity.get().getId(); + } + + private ChessGame getNewChessGame(final Long userId) { + final CampType currentCamp = CampType.WHITE; + final Long chessGameId = chessGameDao.save(new ChessGameEntity(currentCamp.name(), userId)); + final ChessGame chessGame = new ChessGame(currentCamp); + chessBoardService.saveAll(chessGameId, chessGame.getChessBoard()); + return chessGame; + } + + private ChessGame getExistChessGame(final ChessGameEntity chessGameEntity) { final ChessBoard chessBoard = getChessBoard(chessGameEntity); final String currentCamp = chessGameEntity.getCurrentCamp(); return new ChessGame(chessBoard, CampType.from(currentCamp)); diff --git a/src/test/java/chess/dao/chess/MockChessGameDao.java b/src/test/java/chess/dao/chess/MockChessGameDao.java index a5edec77d14..273dbdb0253 100644 --- a/src/test/java/chess/dao/chess/MockChessGameDao.java +++ b/src/test/java/chess/dao/chess/MockChessGameDao.java @@ -24,7 +24,10 @@ public Optional findByUserId(final Long userId) { @Override public Long save(final ChessGameEntity chessGameEntity) { - STORAGE.put(pk.addAndGet(1L), chessGameEntity); + final long key = pk.addAndGet(1L); + ChessGameEntity savedChessGameEntity = new ChessGameEntity(key, + chessGameEntity.getCurrentCamp(), chessGameEntity.getUserId()); + STORAGE.put(key, savedChessGameEntity); return pk.longValue(); } diff --git a/src/test/java/chess/service/ChessGameServiceTest.java b/src/test/java/chess/service/ChessGameServiceTest.java index ac5e8e7be3e..8fd5fa7f320 100644 --- a/src/test/java/chess/service/ChessGameServiceTest.java +++ b/src/test/java/chess/service/ChessGameServiceTest.java @@ -21,9 +21,10 @@ class ChessGameServiceTest { @DisplayName("사용자의 아이디에 해당하는 체스 게임이 존재하지 않으면 새 게임을 반환한다.") void getChessGame_empty() { // given + final MockChessGameDao chessGameDao = new MockChessGameDao(); final ChessGameService chessGameService = new ChessGameService( - new MockChessGameDao(), new ChessBoardService(new MockPieceDao())); - final ChessGame expected = new ChessGame(ChessBoardHelper.createMockBoard(), null); + chessGameDao, new ChessBoardService(new MockPieceDao())); + final ChessGame expected = new ChessGame(CampType.WHITE); // when final ChessGame actual = chessGameService.getChessGame(2L); @@ -38,15 +39,7 @@ void getChessGame_empty() { void getChessGame() { // given final Long userId = 1L; - final Long chessGameId = 1L; - final List pieceEntities = PieceEntityHelper.createPieceEntities(chessGameId); - final MockPieceDao pieceDao = new MockPieceDao(); - pieceEntities.forEach(pieceDao::save); - - final MockChessGameDao chessGameDao = new MockChessGameDao(); - chessGameDao.save(new ChessGameEntity("WHITE", userId)); - - final ChessGameService chessGameService = new ChessGameService(chessGameDao, new ChessBoardService(pieceDao)); + final ChessGameService chessGameService = getChessGameService(userId); final ChessBoard mockProgressBoard = ChessBoardHelper.createMockProgressBoard(); final ChessGame expected = new ChessGame(mockProgressBoard, CampType.WHITE); @@ -57,4 +50,33 @@ void getChessGame() { assertThat(actual) .isEqualTo(expected); } + + @Test + @DisplayName("사용자의 아이디를 기준으로 체스 게임을 조회한다") + void getChessGameId() { + // given + final Long userId = 1L; + final ChessGameService chessGameService = getChessGameService(userId); + + // when + Long chessGameId = chessGameService.getChessGameId(userId); + + // then + assertThat(chessGameId) + .isEqualTo(1L); + } + + private ChessGameService getChessGameService(final Long userId) { + final MockChessGameDao chessGameDao = new MockChessGameDao(); + Long chessGameId = chessGameDao.save(new ChessGameEntity("WHITE", userId)); + final MockPieceDao pieceDao = getMockPieceDao(chessGameId); + return new ChessGameService(chessGameDao, new ChessBoardService(pieceDao)); + } + + private MockPieceDao getMockPieceDao(final Long chessGameId) { + final List pieceEntities = PieceEntityHelper.createPieceEntities(chessGameId); + final MockPieceDao pieceDao = new MockPieceDao(); + pieceEntities.forEach(pieceDao::save); + return pieceDao; + } } From 121bc27b675f3e015da27b3b9747c021fad91905 Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 15:49:46 +0900 Subject: [PATCH 53/76] =?UTF-8?q?feat:=20=EC=B2=B4=EC=8A=A4=EB=A7=90=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=EB=A5=BC=20=EB=B0=94=ED=83=95=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=B2=B4=EC=8A=A4=EB=A7=90=EC=9D=84=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + .../java/chess/service/ChessBoardService.java | 6 ++- .../chess/service/ChessBoardServiceTest.java | 42 +++++++++++++++++-- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 762309db469..38500228ff8 100644 --- a/README.md +++ b/README.md @@ -271,6 +271,7 @@ ### ChessBoardService - [x] 체스 게임 아이디를 기준으로 체스판 정보를 조회한다. +- [x] 체스말 정보를 바탕으로 체스말을 저장한다. --- diff --git a/src/main/java/chess/service/ChessBoardService.java b/src/main/java/chess/service/ChessBoardService.java index facb62ccc2f..856f7b583b1 100644 --- a/src/main/java/chess/service/ChessBoardService.java +++ b/src/main/java/chess/service/ChessBoardService.java @@ -17,9 +17,13 @@ public ChessBoardService(final PieceDao pieceDao) { this.pieceDao = pieceDao; } - public ChessBoard getByChessGameId(final Long chessGameId) { + ChessBoard getByChessGameId(final Long chessGameId) { final List pieceEntities = pieceDao.findByChessGameId(chessGameId); final Map board = ChessBoardMapper.from(pieceEntities); return ChessBoard.create(board); } + + void savePiece(final PieceEntity pieceEntity) { + pieceDao.save(pieceEntity); + } } diff --git a/src/test/java/chess/service/ChessBoardServiceTest.java b/src/test/java/chess/service/ChessBoardServiceTest.java index 4940421625a..0f93ca14eaa 100644 --- a/src/test/java/chess/service/ChessBoardServiceTest.java +++ b/src/test/java/chess/service/ChessBoardServiceTest.java @@ -4,11 +4,18 @@ import chess.dao.chess.PieceDao; import chess.dao.chess.PieceEntityHelper; import chess.domain.board.ChessBoard; +import chess.domain.chess.CampType; +import chess.domain.piece.Pawn; +import chess.domain.piece.Piece; +import chess.domain.piece.PieceType; +import chess.domain.piece.move.Position; import chess.entity.PieceEntity; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.HashMap; import java.util.List; +import java.util.Map; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -18,9 +25,7 @@ class ChessBoardServiceTest { @DisplayName("체스 게임 아이디로 체스판 정보를 조회한다.") void getByChessGameId() { // given - final PieceDao pieceDao = new MockPieceDao(); - final List pieceEntities = PieceEntityHelper.createPieceEntities(1L); - pieceEntities.forEach(pieceDao::save); + final PieceDao pieceDao = createPieceDao(); final ChessBoardService chessBoardService = new ChessBoardService(pieceDao); final ChessBoard expected = ChessBoardHelper.createMockProgressBoard(); @@ -31,4 +36,35 @@ void getByChessGameId() { assertThat(actual) .isEqualTo(expected); } + + @Test + @DisplayName("체스말 정보를 바탕으로 체스말을 저장한다.") + void save() { + // given + final PieceDao pieceDao = new MockPieceDao(); + final ChessBoardService chessBoardService = new ChessBoardService(pieceDao); + final ChessBoard expected = createMockChessBoard(); + + // when + chessBoardService.savePiece(PieceEntity.createWithChessGameId(1L, 1, 1, + "PAWN", "WHITE")); + + // then + final ChessBoard actual = chessBoardService.getByChessGameId(1L); + assertThat(actual) + .isEqualTo(expected); + } + + private PieceDao createPieceDao() { + final PieceDao pieceDao = new MockPieceDao(); + final List pieceEntities = PieceEntityHelper.createPieceEntities(1L); + pieceEntities.forEach(pieceDao::save); + return pieceDao; + } + + private ChessBoard createMockChessBoard() { + final Map mockBoard = new HashMap<>(); + mockBoard.put(new Position(1, 1), new Piece(PieceType.PAWN, CampType.WHITE, new Pawn())); + return ChessBoard.create(mockBoard); + } } From c623a308ce87c39644d2f5ceb548f3aaf13e39cd Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 16:00:19 +0900 Subject: [PATCH 54/76] =?UTF-8?q?feat:=20=EC=9E=85=EB=A0=A5=EB=B0=9B?= =?UTF-8?q?=EC=9D=80=20=EC=9C=84=EC=B9=98=EC=97=90=20=ED=95=B4=EB=8B=B9?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EC=B2=B4=EC=8A=A4=EB=A7=90=EC=9D=84=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + src/main/java/chess/entity/PieceEntity.java | 16 +++++++++++--- .../java/chess/service/ChessBoardService.java | 5 +++++ .../chess/service/ChessBoardServiceTest.java | 21 +++++++++++++++++++ 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 38500228ff8..69022f84029 100644 --- a/README.md +++ b/README.md @@ -272,6 +272,7 @@ - [x] 체스 게임 아이디를 기준으로 체스판 정보를 조회한다. - [x] 체스말 정보를 바탕으로 체스말을 저장한다. +- [x] 입력받은 위치에 해당하는 체스말을 제거한다. --- diff --git a/src/main/java/chess/entity/PieceEntity.java b/src/main/java/chess/entity/PieceEntity.java index d5093eed19b..78b76556036 100644 --- a/src/main/java/chess/entity/PieceEntity.java +++ b/src/main/java/chess/entity/PieceEntity.java @@ -7,8 +7,8 @@ public final class PieceEntity { private Long chessGameId; private final Integer rank; private final Integer file; - private final String pieceType; - private final String campType; + private String pieceType; + private String campType; private PieceEntity(final Long id, final Long chessGameId, final Integer rank, final Integer file, final String pieceType, final String campType) { @@ -20,6 +20,12 @@ private PieceEntity(final Long id, final Long chessGameId, final Integer rank, this.campType = campType; } + public PieceEntity(final Long chessGameId, final Integer rank, final Integer file) { + this.chessGameId = chessGameId; + this.rank = rank; + this.file = file; + } + public static PieceEntity createWithId(final Long id, final Integer rank, final Integer file, final String pieceType, final String campType) { return new PieceEntity(id, null, rank, file, pieceType, campType); @@ -29,7 +35,11 @@ public static PieceEntity createWithChessGameId(final Long chessGameId, final In final String pieceType, final String campType) { return new PieceEntity(null, chessGameId, rank, file, pieceType, campType); } - + + public static PieceEntity createWithLocation(final Long chessGameId, final Integer rank, final Integer file) { + return new PieceEntity(chessGameId, rank, file); + } + @Override public boolean equals(final Object o) { if (this == o) return true; diff --git a/src/main/java/chess/service/ChessBoardService.java b/src/main/java/chess/service/ChessBoardService.java index 856f7b583b1..99a12f3b9a8 100644 --- a/src/main/java/chess/service/ChessBoardService.java +++ b/src/main/java/chess/service/ChessBoardService.java @@ -26,4 +26,9 @@ ChessBoard getByChessGameId(final Long chessGameId) { void savePiece(final PieceEntity pieceEntity) { pieceDao.save(pieceEntity); } + + void deletePieces(final PieceEntity sourcePiece, final PieceEntity targetPiece) { + final Long chessGameId = sourcePiece.getChessGameId(); + pieceDao.deleteByPositions(chessGameId, sourcePiece, targetPiece); + } } diff --git a/src/test/java/chess/service/ChessBoardServiceTest.java b/src/test/java/chess/service/ChessBoardServiceTest.java index 0f93ca14eaa..fb3a9270b19 100644 --- a/src/test/java/chess/service/ChessBoardServiceTest.java +++ b/src/test/java/chess/service/ChessBoardServiceTest.java @@ -13,6 +13,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -55,6 +56,26 @@ void save() { .isEqualTo(expected); } + @Test + @DisplayName("입력받은 위치에 해당하는 체스말을 제거한다") + void deletePieces() { + // given + final PieceDao pieceDao = new MockPieceDao(); + final ChessBoardService chessBoardService = new ChessBoardService(pieceDao); + final PieceEntity source = PieceEntity.createWithLocation(1L, 0, 0); + final PieceEntity target = PieceEntity.createWithLocation(1L, 0, 1); + chessBoardService.savePiece(source); + chessBoardService.savePiece(target); + + // when + chessBoardService.deletePieces(source, target); + + // then + final ChessBoard actual = chessBoardService.getByChessGameId(1L); + assertThat(actual) + .isEqualTo(ChessBoard.create(Collections.emptyMap())); + } + private PieceDao createPieceDao() { final PieceDao pieceDao = new MockPieceDao(); final List pieceEntities = PieceEntityHelper.createPieceEntities(1L); From 7df40181ee71457fdafd1b18a52cdba4493f148d Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 16:03:55 +0900 Subject: [PATCH 55/76] =?UTF-8?q?feat:=20=EC=B2=B4=EC=8A=A4=ED=8C=90?= =?UTF-8?q?=EC=9D=98=20=EB=AA=A8=EB=93=A0=20=EA=B8=B0=EB=AC=BC=EC=9D=84=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + .../java/chess/service/ChessBoardService.java | 9 +++++++++ .../chess/service/ChessBoardServiceTest.java | 16 ++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/README.md b/README.md index 69022f84029..81880cf9179 100644 --- a/README.md +++ b/README.md @@ -273,6 +273,7 @@ - [x] 체스 게임 아이디를 기준으로 체스판 정보를 조회한다. - [x] 체스말 정보를 바탕으로 체스말을 저장한다. - [x] 입력받은 위치에 해당하는 체스말을 제거한다. +- [x] 체스판의 모든 기물을 저장한다. --- diff --git a/src/main/java/chess/service/ChessBoardService.java b/src/main/java/chess/service/ChessBoardService.java index 99a12f3b9a8..9d8d31e1026 100644 --- a/src/main/java/chess/service/ChessBoardService.java +++ b/src/main/java/chess/service/ChessBoardService.java @@ -31,4 +31,13 @@ void deletePieces(final PieceEntity sourcePiece, final PieceEntity targetPiece) final Long chessGameId = sourcePiece.getChessGameId(); pieceDao.deleteByPositions(chessGameId, sourcePiece, targetPiece); } + + void saveAll(final Long chessGameId, final Map chessBoard) { + for (Position position : chessBoard.keySet()) { + final Piece piece = chessBoard.get(position); + PieceEntity pieceEntity = PieceEntity.createWithChessGameId(chessGameId, position.getRank(), + position.getFile(), piece.getPieceType().name(), piece.getCampType().name()); + pieceDao.save(pieceEntity); + } + } } diff --git a/src/test/java/chess/service/ChessBoardServiceTest.java b/src/test/java/chess/service/ChessBoardServiceTest.java index fb3a9270b19..43f4ec91d3e 100644 --- a/src/test/java/chess/service/ChessBoardServiceTest.java +++ b/src/test/java/chess/service/ChessBoardServiceTest.java @@ -76,6 +76,22 @@ void deletePieces() { .isEqualTo(ChessBoard.create(Collections.emptyMap())); } + @Test + @DisplayName("체스판의 모든 기물을 저장한다") + void saveAll() { + // given + final PieceDao pieceDao = new MockPieceDao(); + final ChessBoardService chessBoardService = new ChessBoardService(pieceDao); + + // when + chessBoardService.saveAll(1L, createMockChessBoard().getBoard()); + + // then + final ChessBoard actual = chessBoardService.getByChessGameId(1L); + assertThat(actual) + .isEqualTo(createMockChessBoard()); + } + private PieceDao createPieceDao() { final PieceDao pieceDao = new MockPieceDao(); final List pieceEntities = PieceEntityHelper.createPieceEntities(1L); From ec1db9c9417e964f6eae58cbb72cc12f7e1da452 Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 16:09:19 +0900 Subject: [PATCH 56/76] =?UTF-8?q?feat:=20=EC=B2=B4=EC=8A=A4=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=20=EC=95=84=EC=9D=B4=EB=94=94=EC=97=90=20=ED=95=B4?= =?UTF-8?q?=EB=8B=B9=ED=95=98=EB=8A=94=20=EB=AA=A8=EB=93=A0=20=EA=B8=B0?= =?UTF-8?q?=EB=AC=BC=EC=9D=84=20=EC=A0=9C=EA=B1=B0=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + .../java/chess/service/ChessBoardService.java | 4 ++++ .../chess/service/ChessBoardServiceTest.java | 24 ++++++++++++++++--- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 81880cf9179..7e845d11ae2 100644 --- a/README.md +++ b/README.md @@ -274,6 +274,7 @@ - [x] 체스말 정보를 바탕으로 체스말을 저장한다. - [x] 입력받은 위치에 해당하는 체스말을 제거한다. - [x] 체스판의 모든 기물을 저장한다. +- [x] 체스 게임 아이디에 해당하는 모든 기물을 제거한다. --- diff --git a/src/main/java/chess/service/ChessBoardService.java b/src/main/java/chess/service/ChessBoardService.java index 9d8d31e1026..3a74cc46e1e 100644 --- a/src/main/java/chess/service/ChessBoardService.java +++ b/src/main/java/chess/service/ChessBoardService.java @@ -40,4 +40,8 @@ void saveAll(final Long chessGameId, final Map chessBoard) { pieceDao.save(pieceEntity); } } + + void deleteByChessGameId(final Long chessGameId) { + pieceDao.deleteByChessGameId(chessGameId); + } } diff --git a/src/test/java/chess/service/ChessBoardServiceTest.java b/src/test/java/chess/service/ChessBoardServiceTest.java index 43f4ec91d3e..00993e1d58a 100644 --- a/src/test/java/chess/service/ChessBoardServiceTest.java +++ b/src/test/java/chess/service/ChessBoardServiceTest.java @@ -26,7 +26,8 @@ class ChessBoardServiceTest { @DisplayName("체스 게임 아이디로 체스판 정보를 조회한다.") void getByChessGameId() { // given - final PieceDao pieceDao = createPieceDao(); + final Long chessGameId = 1L; + final PieceDao pieceDao = createPieceDao(chessGameId); final ChessBoardService chessBoardService = new ChessBoardService(pieceDao); final ChessBoard expected = ChessBoardHelper.createMockProgressBoard(); @@ -92,9 +93,26 @@ void saveAll() { .isEqualTo(createMockChessBoard()); } - private PieceDao createPieceDao() { + @Test + @DisplayName("체스 게임 아이디에 해당하는 모든 기물을 제거한다") + void deleteByChessGameId() { + // given + final Long chessGameId = 1L; + final PieceDao pieceDao = createPieceDao(chessGameId); + final ChessBoardService chessBoardService = new ChessBoardService(pieceDao); + + // when + chessBoardService.deleteByChessGameId(chessGameId); + + // then + final ChessBoard expected = chessBoardService.getByChessGameId(1L); + assertThat(expected) + .isEqualTo(ChessBoard.create(Collections.emptyMap())); + } + + private PieceDao createPieceDao(final Long chessGameId) { final PieceDao pieceDao = new MockPieceDao(); - final List pieceEntities = PieceEntityHelper.createPieceEntities(1L); + final List pieceEntities = PieceEntityHelper.createPieceEntities(chessGameId); pieceEntities.forEach(pieceDao::save); return pieceDao; } From 06bf99d4a21837529eb2e0a9f425f49b98858819 Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 16:19:12 +0900 Subject: [PATCH 57/76] =?UTF-8?q?feat:=20=EC=B2=B4=EC=8A=A4=EB=A7=90=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=EB=A5=BC=20=EB=B0=94=ED=83=95=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=B2=B4=EC=8A=A4=EB=A7=90=EC=9D=84=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++++ .../java/chess/service/ChessBoardService.java | 2 +- .../java/chess/service/ChessGameService.java | 5 +++++ .../chess/service/ChessGameServiceTest.java | 17 +++++++++++++++++ 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7e845d11ae2..e446eb39ab3 100644 --- a/README.md +++ b/README.md @@ -267,6 +267,10 @@ - [x] 사용자의 아이디에 해당하는 체스 게임이 존재하면 해당 게임을 반환하고, 아니라면 새 게임을 반환한다. - [x] 사용자의 아이디를 기준으로 체스 게임을 조회한다. +- [x] 체스말 정보를 바탕으로 체스말을 저장한다. +- [ ] 체스 게임 아이디에 해당하는 진영 정보를 업데이트한다. +- [ ] 입력받은 위치에 해당하는 체스말을 제거한다. +- [ ] 사용자의 아이디에 해당하는 체스 기물과 체스판 정보를 제거한다. ### ChessBoardService diff --git a/src/main/java/chess/service/ChessBoardService.java b/src/main/java/chess/service/ChessBoardService.java index 3a74cc46e1e..4cdf1ee0f86 100644 --- a/src/main/java/chess/service/ChessBoardService.java +++ b/src/main/java/chess/service/ChessBoardService.java @@ -13,7 +13,7 @@ public class ChessBoardService { private final PieceDao pieceDao; - public ChessBoardService(final PieceDao pieceDao) { + ChessBoardService(final PieceDao pieceDao) { this.pieceDao = pieceDao; } diff --git a/src/main/java/chess/service/ChessGameService.java b/src/main/java/chess/service/ChessGameService.java index 14221404c97..de2b19e45d1 100644 --- a/src/main/java/chess/service/ChessGameService.java +++ b/src/main/java/chess/service/ChessGameService.java @@ -5,6 +5,7 @@ import chess.domain.chess.CampType; import chess.domain.chess.ChessGame; import chess.entity.ChessGameEntity; +import chess.entity.PieceEntity; import java.util.Optional; @@ -34,6 +35,10 @@ public Long getChessGameId(final Long userId) { return findChessGameEntity.get().getId(); } + public void savePiece(final PieceEntity pieceEntity) { + chessBoardService.savePiece(pieceEntity); + } + private ChessGame getNewChessGame(final Long userId) { final CampType currentCamp = CampType.WHITE; final Long chessGameId = chessGameDao.save(new ChessGameEntity(currentCamp.name(), userId)); diff --git a/src/test/java/chess/service/ChessGameServiceTest.java b/src/test/java/chess/service/ChessGameServiceTest.java index 8fd5fa7f320..d3807bbf5c5 100644 --- a/src/test/java/chess/service/ChessGameServiceTest.java +++ b/src/test/java/chess/service/ChessGameServiceTest.java @@ -66,6 +66,23 @@ void getChessGameId() { .isEqualTo(1L); } + @Test + @DisplayName("체스말 정보를 바탕으로 체스말을 저장한다") + void savePiece() { + // given + final Long userId = 1L; + final ChessGameService chessGameService = getChessGameService(userId); + + // when + chessGameService.savePiece(PieceEntity.createWithChessGameId(1L, 1, 1, + "PAWN", "WHITE")); + + // then + Long chessGameId = chessGameService.getChessGameId(1L); + assertThat(chessGameId) + .isEqualTo(1L); + } + private ChessGameService getChessGameService(final Long userId) { final MockChessGameDao chessGameDao = new MockChessGameDao(); Long chessGameId = chessGameDao.save(new ChessGameEntity("WHITE", userId)); From 1c461e71102c5e64b5164cbfe463d6bf81c7c0b3 Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 16:23:00 +0900 Subject: [PATCH 58/76] =?UTF-8?q?feat:=20=EC=B2=B4=EC=8A=A4=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=20=EC=95=84=EC=9D=B4=EB=94=94=EC=97=90=20=ED=95=B4?= =?UTF-8?q?=EB=8B=B9=ED=95=98=EB=8A=94=20=EC=A7=84=EC=98=81=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EB=A5=BC=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../java/chess/service/ChessGameService.java | 4 ++++ .../chess/service/ChessGameServiceTest.java | 20 ++++++++++++++++++- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e446eb39ab3..44e88b4a59b 100644 --- a/README.md +++ b/README.md @@ -268,7 +268,7 @@ - [x] 사용자의 아이디에 해당하는 체스 게임이 존재하면 해당 게임을 반환하고, 아니라면 새 게임을 반환한다. - [x] 사용자의 아이디를 기준으로 체스 게임을 조회한다. - [x] 체스말 정보를 바탕으로 체스말을 저장한다. -- [ ] 체스 게임 아이디에 해당하는 진영 정보를 업데이트한다. +- [x] 체스 게임 아이디에 해당하는 진영 정보를 업데이트한다. - [ ] 입력받은 위치에 해당하는 체스말을 제거한다. - [ ] 사용자의 아이디에 해당하는 체스 기물과 체스판 정보를 제거한다. diff --git a/src/main/java/chess/service/ChessGameService.java b/src/main/java/chess/service/ChessGameService.java index de2b19e45d1..59790b17dc8 100644 --- a/src/main/java/chess/service/ChessGameService.java +++ b/src/main/java/chess/service/ChessGameService.java @@ -39,6 +39,10 @@ public void savePiece(final PieceEntity pieceEntity) { chessBoardService.savePiece(pieceEntity); } + public void updateCurrentCamp(final Long chessGameId, final CampType currentCamp) { + chessGameDao.updateCurrentCampById(chessGameId, currentCamp); + } + private ChessGame getNewChessGame(final Long userId) { final CampType currentCamp = CampType.WHITE; final Long chessGameId = chessGameDao.save(new ChessGameEntity(currentCamp.name(), userId)); diff --git a/src/test/java/chess/service/ChessGameServiceTest.java b/src/test/java/chess/service/ChessGameServiceTest.java index d3807bbf5c5..91ea4e3c92e 100644 --- a/src/test/java/chess/service/ChessGameServiceTest.java +++ b/src/test/java/chess/service/ChessGameServiceTest.java @@ -78,11 +78,29 @@ void savePiece() { "PAWN", "WHITE")); // then - Long chessGameId = chessGameService.getChessGameId(1L); + final Long chessGameId = chessGameService.getChessGameId(1L); assertThat(chessGameId) .isEqualTo(1L); } + @Test + @DisplayName("체스 게임 아이디에 해당하는 진영 정보를 업데이트한다.") + void updateCurrentCamp() { + // given + final Long userId = 1L; + final ChessGameService chessGameService = getChessGameService(userId); + final CampType changedCamp = CampType.BLACK; + + // when + chessGameService.updateCurrentCamp(1L, changedCamp); + + // then + final ChessGame chessGame = chessGameService.getChessGame(1L); + final CampType campType = chessGame.getCurrentCamp(); + assertThat(campType) + .isEqualTo(changedCamp); + } + private ChessGameService getChessGameService(final Long userId) { final MockChessGameDao chessGameDao = new MockChessGameDao(); Long chessGameId = chessGameDao.save(new ChessGameEntity("WHITE", userId)); From 6593a07f95d1808d3f28b4f392fd2f5162c622b4 Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 16:35:28 +0900 Subject: [PATCH 59/76] =?UTF-8?q?feat:=20=EC=9E=85=EB=A0=A5=EB=B0=9B?= =?UTF-8?q?=EC=9D=80=20=EC=9C=84=EC=B9=98=EC=97=90=20=ED=95=B4=EB=8B=B9?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EC=B2=B4=EC=8A=A4=EB=A7=90=EC=9D=84=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../java/chess/service/ChessGameService.java | 4 ++++ .../chess/service/ChessGameServiceTest.java | 21 +++++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 44e88b4a59b..8a84497a178 100644 --- a/README.md +++ b/README.md @@ -269,7 +269,7 @@ - [x] 사용자의 아이디를 기준으로 체스 게임을 조회한다. - [x] 체스말 정보를 바탕으로 체스말을 저장한다. - [x] 체스 게임 아이디에 해당하는 진영 정보를 업데이트한다. -- [ ] 입력받은 위치에 해당하는 체스말을 제거한다. +- [x] 입력받은 위치에 해당하는 체스말을 제거한다. - [ ] 사용자의 아이디에 해당하는 체스 기물과 체스판 정보를 제거한다. ### ChessBoardService diff --git a/src/main/java/chess/service/ChessGameService.java b/src/main/java/chess/service/ChessGameService.java index 59790b17dc8..d316cf75470 100644 --- a/src/main/java/chess/service/ChessGameService.java +++ b/src/main/java/chess/service/ChessGameService.java @@ -43,6 +43,10 @@ public void updateCurrentCamp(final Long chessGameId, final CampType currentCamp chessGameDao.updateCurrentCampById(chessGameId, currentCamp); } + public void deletePieces(final PieceEntity sourcePiece, final PieceEntity targetPiece) { + chessBoardService.deletePieces(sourcePiece, targetPiece); + } + private ChessGame getNewChessGame(final Long userId) { final CampType currentCamp = CampType.WHITE; final Long chessGameId = chessGameDao.save(new ChessGameEntity(currentCamp.name(), userId)); diff --git a/src/test/java/chess/service/ChessGameServiceTest.java b/src/test/java/chess/service/ChessGameServiceTest.java index 91ea4e3c92e..998379a6614 100644 --- a/src/test/java/chess/service/ChessGameServiceTest.java +++ b/src/test/java/chess/service/ChessGameServiceTest.java @@ -11,6 +11,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.util.Collections; import java.util.List; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -101,6 +102,26 @@ void updateCurrentCamp() { .isEqualTo(changedCamp); } + @Test + @DisplayName("입력받은 위치에 해당하는 체스말을 제거한다") + void deletePieces() { + // given + final Long userId = 1L; + final MockChessGameDao chessGameDao = new MockChessGameDao(); + chessGameDao.save(new ChessGameEntity("WHITE", userId)); + final ChessGameService chessGameService = new ChessGameService(chessGameDao, new ChessBoardService(new MockPieceDao())); + final PieceEntity source = PieceEntity.createWithLocation(1L, 0, 0); + final PieceEntity target = PieceEntity.createWithLocation(1L, 0, 1); + + // when + chessGameService.deletePieces(source, target); + + // then + final ChessGame actual = chessGameService.getChessGame(1L); + assertThat(actual) + .isEqualTo(new ChessGame(ChessBoard.create(Collections.emptyMap()), CampType.WHITE)); + } + private ChessGameService getChessGameService(final Long userId) { final MockChessGameDao chessGameDao = new MockChessGameDao(); Long chessGameId = chessGameDao.save(new ChessGameEntity("WHITE", userId)); From cb18d5dd6242bfc8deafda760c7394fd2ea6bc9f Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 16:45:55 +0900 Subject: [PATCH 60/76] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EC=9D=98=20=EC=95=84=EC=9D=B4=EB=94=94=EC=97=90=20=ED=95=B4?= =?UTF-8?q?=EB=8B=B9=ED=95=98=EB=8A=94=20=EC=B2=B4=EC=8A=A4=20=EA=B8=B0?= =?UTF-8?q?=EB=AC=BC=EA=B3=BC=20=EC=B2=B4=EC=8A=A4=ED=8C=90=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EB=A5=BC=20=EC=A0=9C=EA=B1=B0=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../java/chess/service/ChessGameService.java | 6 ++++++ .../chess/service/ChessGameServiceTest.java | 17 +++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8a84497a178..0d90933215f 100644 --- a/README.md +++ b/README.md @@ -270,7 +270,7 @@ - [x] 체스말 정보를 바탕으로 체스말을 저장한다. - [x] 체스 게임 아이디에 해당하는 진영 정보를 업데이트한다. - [x] 입력받은 위치에 해당하는 체스말을 제거한다. -- [ ] 사용자의 아이디에 해당하는 체스 기물과 체스판 정보를 제거한다. +- [x] 사용자의 아이디에 해당하는 체스 기물과 체스판 정보를 제거한다. ### ChessBoardService diff --git a/src/main/java/chess/service/ChessGameService.java b/src/main/java/chess/service/ChessGameService.java index d316cf75470..5f0d03f0115 100644 --- a/src/main/java/chess/service/ChessGameService.java +++ b/src/main/java/chess/service/ChessGameService.java @@ -47,6 +47,12 @@ public void deletePieces(final PieceEntity sourcePiece, final PieceEntity target chessBoardService.deletePieces(sourcePiece, targetPiece); } + public void clear(final Long userId) { + final Long chessGameId = getChessGameId(userId); + chessBoardService.deleteByChessGameId(chessGameId); + chessGameDao.deleteByUserId(userId); + } + private ChessGame getNewChessGame(final Long userId) { final CampType currentCamp = CampType.WHITE; final Long chessGameId = chessGameDao.save(new ChessGameEntity(currentCamp.name(), userId)); diff --git a/src/test/java/chess/service/ChessGameServiceTest.java b/src/test/java/chess/service/ChessGameServiceTest.java index 998379a6614..69f62af3b63 100644 --- a/src/test/java/chess/service/ChessGameServiceTest.java +++ b/src/test/java/chess/service/ChessGameServiceTest.java @@ -122,6 +122,23 @@ void deletePieces() { .isEqualTo(new ChessGame(ChessBoard.create(Collections.emptyMap()), CampType.WHITE)); } + @Test + @DisplayName("사용자의 아이디에 해당하는 체스 기물과 체스판 정보를 제거한다") + void clear() { + // given + final Long userId = 1L; + final ChessGameService chessGameService = getChessGameService(userId); + + // when + chessGameService.clear(userId); + + // then + final ChessGame chessGame = chessGameService.getChessGame(userId); + final ChessGame expected = new ChessGame(CampType.WHITE); + assertThat(chessGame) + .isEqualTo(expected); + } + private ChessGameService getChessGameService(final Long userId) { final MockChessGameDao chessGameDao = new MockChessGameDao(); Long chessGameId = chessGameDao.save(new ChessGameEntity("WHITE", userId)); From e8390b5219336fe39242ebab697955d599421b06 Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 16:48:04 +0900 Subject: [PATCH 61/76] =?UTF-8?q?feat:=20=EC=84=9C=EB=B9=84=EC=8A=A4?= =?UTF-8?q?=EC=9D=98=20=EC=83=9D=EC=84=B1=EC=9D=84=20=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A5=BC=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +++ .../java/chess/service/ServiceManager.java | 27 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 src/main/java/chess/service/ServiceManager.java diff --git a/README.md b/README.md index 0d90933215f..f103035dae8 100644 --- a/README.md +++ b/README.md @@ -280,6 +280,10 @@ - [x] 체스판의 모든 기물을 저장한다. - [x] 체스 게임 아이디에 해당하는 모든 기물을 제거한다. +### ServiceManager + +- [x] 서비스의 생성을 총괄한다. + --- ## ✨domain - view diff --git a/src/main/java/chess/service/ServiceManager.java b/src/main/java/chess/service/ServiceManager.java new file mode 100644 index 00000000000..0e29d957ee1 --- /dev/null +++ b/src/main/java/chess/service/ServiceManager.java @@ -0,0 +1,27 @@ +package chess.service; + +import chess.dao.chess.ChessGameDao; +import chess.dao.chess.ChessGameDaoImpl; +import chess.dao.chess.PieceDao; +import chess.dao.chess.PieceDaoImpl; +import chess.dao.user.UserDaoImpl; +import chess.database.JdbcTemplate; + +public final class ServiceManager { + private final JdbcTemplate jdbcTemplate; + + public ServiceManager(final JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + public UserService userService() { + return new UserService(new UserDaoImpl(jdbcTemplate)); + } + + public ChessGameService chessGameService() { + final ChessGameDao chessGameDao = new ChessGameDaoImpl(jdbcTemplate); + final PieceDao pieceDao = new PieceDaoImpl(jdbcTemplate); + final ChessBoardService chessBoardService = new ChessBoardService(pieceDao); + return new ChessGameService(chessGameDao, chessBoardService); + } +} From d4aeaea388ed9ea166524e91f4adb39743241778 Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 16:51:17 +0900 Subject: [PATCH 62/76] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90?= =?UTF-8?q?=EC=97=90=EA=B2=8C=20=EC=9D=B4=EB=A6=84=EC=9D=84=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=EB=B0=9B=EB=8A=94=20=EA=B8=B0=EB=8A=A5=EC=9D=84=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + src/main/java/chess/view/InputView.java | 4 ++++ src/main/java/chess/view/OutputView.java | 6 ++++++ 3 files changed, 11 insertions(+) diff --git a/README.md b/README.md index f103035dae8..cb4d07f43f8 100644 --- a/README.md +++ b/README.md @@ -294,6 +294,7 @@ ### OutputView +- [x] 사용자에게 이름을 입력받는 메시지를 출력한다. - [x] 게임 안내 메시지를 출력한다. - [x] 체스판에 있는 체스말을 출력하고, 비어있는 곳은 .으로 출력한다. - [x] 각 진영의 점수와 이긴 진영에 대해서 출력한다. diff --git a/src/main/java/chess/view/InputView.java b/src/main/java/chess/view/InputView.java index 22b1063c440..579815b7138 100644 --- a/src/main/java/chess/view/InputView.java +++ b/src/main/java/chess/view/InputView.java @@ -14,6 +14,10 @@ public static List getCommands() { return Arrays.asList(command.split(DELIMITER)); } + public static String getCommand() { + return readCommand(); + } + private static String readCommand() { final String command = scanner.nextLine(); if (command == null || command.isBlank()) { diff --git a/src/main/java/chess/view/OutputView.java b/src/main/java/chess/view/OutputView.java index ffa9af36838..3292893230b 100644 --- a/src/main/java/chess/view/OutputView.java +++ b/src/main/java/chess/view/OutputView.java @@ -23,6 +23,8 @@ public final class OutputView { "> 흑진영 (BLACK) : %.1f\n" + "> 승리한 팀 : %s\n"; + private static final String USER_NAME_INPUT_MESSAGE = "플레이어님의 이름을 입력해 주세요. (1~20자)"; + private static final String DRAW = "DRAW!"; private static final String WHITE = "WHITE"; private static final String BLACK = "BLACK"; @@ -32,6 +34,10 @@ public static void print(final String message) { System.out.println(message); } + public static void printUserNameInputMessage() { + print(USER_NAME_INPUT_MESSAGE); + } + public static void printStartMessage() { print(String.format(START_MESSAGE, START.name().toLowerCase(), END.name().toLowerCase(), MOVE.name().toLowerCase())); From 89913cd93306b49181044bebc45fa7e69f621275 Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 17:03:29 +0900 Subject: [PATCH 63/76] =?UTF-8?q?feat:=20ServiceManager=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20mock=20=EA=B0=9D=EC=B2=B4=EB=A5=BC=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/service/Service.java | 7 +++++++ .../java/chess/service/ServiceManager.java | 4 +++- .../java/chess/service/MockServiceManager.java | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/main/java/chess/service/Service.java create mode 100644 src/test/java/chess/service/MockServiceManager.java diff --git a/src/main/java/chess/service/Service.java b/src/main/java/chess/service/Service.java new file mode 100644 index 00000000000..255e6d22aeb --- /dev/null +++ b/src/main/java/chess/service/Service.java @@ -0,0 +1,7 @@ +package chess.service; + +public interface Service { + UserService userService(); + + ChessGameService chessGameService(); +} diff --git a/src/main/java/chess/service/ServiceManager.java b/src/main/java/chess/service/ServiceManager.java index 0e29d957ee1..612993407b1 100644 --- a/src/main/java/chess/service/ServiceManager.java +++ b/src/main/java/chess/service/ServiceManager.java @@ -7,17 +7,19 @@ import chess.dao.user.UserDaoImpl; import chess.database.JdbcTemplate; -public final class ServiceManager { +public final class ServiceManager implements Service { private final JdbcTemplate jdbcTemplate; public ServiceManager(final JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } + @Override public UserService userService() { return new UserService(new UserDaoImpl(jdbcTemplate)); } + @Override public ChessGameService chessGameService() { final ChessGameDao chessGameDao = new ChessGameDaoImpl(jdbcTemplate); final PieceDao pieceDao = new PieceDaoImpl(jdbcTemplate); diff --git a/src/test/java/chess/service/MockServiceManager.java b/src/test/java/chess/service/MockServiceManager.java new file mode 100644 index 00000000000..2d189a3c91b --- /dev/null +++ b/src/test/java/chess/service/MockServiceManager.java @@ -0,0 +1,18 @@ +package chess.service; + +import chess.dao.chess.MockChessGameDao; +import chess.dao.chess.MockPieceDao; +import chess.dao.user.MockUserDao; + +public class MockServiceManager implements Service { + @Override + public UserService userService() { + return new UserService(new MockUserDao()); + } + + @Override + public ChessGameService chessGameService() { + final ChessBoardService chessBoardService = new ChessBoardService(new MockPieceDao()); + return new ChessGameService(new MockChessGameDao(), chessBoardService); + } +} From 165e84732148cd27bf05119184e1ce45c05c7e80 Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 17:04:42 +0900 Subject: [PATCH 64/76] =?UTF-8?q?feat:=20=EC=9D=B4=EB=8F=99=20=EC=8B=9C=20?= =?UTF-8?q?=EA=B2=8C=EC=9E=84=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EB=A5=BC=20=EC=A0=80=EC=9E=A5=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/status/MoveController.java | 71 ++++++++++++++----- .../controller/status/MoveControllerTest.java | 60 ++++++---------- .../java/chess/service/ChessBoardHelper.java | 36 +--------- 3 files changed, 79 insertions(+), 88 deletions(-) diff --git a/src/main/java/chess/controller/status/MoveController.java b/src/main/java/chess/controller/status/MoveController.java index c41c9f14db5..76690820537 100644 --- a/src/main/java/chess/controller/status/MoveController.java +++ b/src/main/java/chess/controller/status/MoveController.java @@ -1,24 +1,32 @@ package chess.controller.status; import chess.controller.Command; -import chess.domain.chess.CampType; +import chess.controller.mapper.ChessBoardDtoMapper; import chess.domain.chess.ChessGame; +import chess.domain.piece.Piece; import chess.domain.piece.move.Position; import chess.domain.piece.move.PositionConverter; +import chess.entity.PieceEntity; +import chess.service.ChessGameService; +import chess.view.OutputView; import java.util.List; +import java.util.Map; public final class MoveController implements Controller { + + private final Long userId; private final ChessGame chessGame; - private final CampType campType; + private final ChessGameService chessGameService; - MoveController(final ChessGame chessGame, final CampType campType) { - this.chessGame = chessGame; - this.campType = campType; + MoveController(final Long userId, final ChessGameService chessGameService) { + this.userId = userId; + this.chessGame = chessGameService.getChessGame(userId); + this.chessGameService = chessGameService; } @Override - public Controller checkCommand(final Command command, final Runnable runnable) { + public Controller checkCommand(final Command command) { if (command.isStart()) { throw new IllegalArgumentException("이미 시작이 완료되었습니다."); } @@ -26,9 +34,9 @@ public Controller checkCommand(final Command command, final Runnable runnable) { return new EndController(); } if (command.isStatus()) { - return new StatusController(chessGame, campType).getStatus(true); + return new StatusController(userId, chessGameService).getStatus(true); } - return move(command, runnable); + return move(command); } @Override @@ -36,17 +44,20 @@ public boolean isRun() { return true; } - Controller move(final Command command, final Runnable runnable) { + @Override + public void printBoard() { + OutputView.printBoard(ChessBoardDtoMapper.createChessBoardDto(chessGame.getChessBoard())); + } + + Controller move(final Command command) { validateCommand(command); final List commands = command.getCommands(); - final Position source = PositionConverter.convert(commands.get(1)); - final Position target = PositionConverter.convert(commands.get(2)); - boolean isGameRun = chessGame.run(source, target, campType); - runnable.run(); - if (!isGameRun) { - return new StatusController(chessGame, campType).getStatus(false); + + play(commands); + if (!chessGame.isKingAlive()) { + return new StatusController(userId, chessGameService).getStatus(false); } - return new MoveController(chessGame, campType.changeTurn()); + return new MoveController(userId, chessGameService); } private void validateCommand(final Command command) { @@ -54,4 +65,32 @@ private void validateCommand(final Command command) { throw new IllegalArgumentException("'move source위치 target위치 - 예. move b2 b3'와 같은 형태로 입력해 주세요."); } } + + private void play(final List commands) { + final Position source = PositionConverter.convert(commands.get(1)); + final Position target = PositionConverter.convert(commands.get(2)); + chessGame.play(source, target); + savePlayInfo(source, target); + } + + private void savePlayInfo(final Position source, final Position target) { + final Long chessGameId = chessGameService.getChessGameId(userId); + deletePieces(source, target, chessGameId); + savePieces(target, chessGameId); + chessGameService.updateCurrentCamp(chessGameId, chessGame.getCurrentCamp()); + } + + private void deletePieces(final Position source, final Position target, final Long chessGameId) { + final PieceEntity sourcePiece = PieceEntity.createWithLocation(chessGameId, source.getRank(), source.getFile()); + final PieceEntity targetPiece = PieceEntity.createWithLocation(chessGameId, target.getRank(), target.getFile()); + chessGameService.deletePieces(sourcePiece, targetPiece); + } + + private void savePieces(final Position target, final Long chessGameId) { + final Map chessBoard = chessGame.getChessBoard(); + final Piece piece = chessBoard.get(target); + final PieceEntity savedPiece = PieceEntity.createWithChessGameId(chessGameId, target.getRank(), + target.getFile(), piece.getPieceType().name(), piece.getCampType().name()); + chessGameService.savePiece(savedPiece); + } } diff --git a/src/test/java/chess/controller/status/MoveControllerTest.java b/src/test/java/chess/controller/status/MoveControllerTest.java index 764bf1429d7..05d5374461a 100644 --- a/src/test/java/chess/controller/status/MoveControllerTest.java +++ b/src/test/java/chess/controller/status/MoveControllerTest.java @@ -2,12 +2,13 @@ import chess.controller.Command; import chess.controller.CommandType; -import chess.domain.chess.CampType; -import chess.domain.chess.ChessGame; -import chess.domain.chess.ChessGameHelper; -import chess.domain.piece.move.Position; +import chess.service.ChessGameService; +import chess.service.MockServiceManager; +import chess.service.Service; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -17,18 +18,26 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class MoveControllerTest { + private ChessGameService chessGameService; + + @BeforeAll + void init() { + final Service mockServiceManager = new MockServiceManager(); + chessGameService = mockServiceManager.chessGameService(); + } + @Test @DisplayName(value = "게임이 움직임 상태일 때 start를 입력하면 예외가 발생한다.") void checkCommandStart() { // given - final MoveController moveController = new MoveController(new ChessGame(), CampType.WHITE); + final MoveController moveController = new MoveController(1L, chessGameService); final Command command = new Command(CommandType.START, List.of("start")); // when, then - assertThatThrownBy(() -> moveController.checkCommand(command, () -> { - })) + assertThatThrownBy(() -> moveController.checkCommand(command)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("이미 시작이 완료되었습니다."); } @@ -37,12 +46,11 @@ void checkCommandStart() { @DisplayName(value = "게임이 움직임 상태일 때 end를 입력하면 게임이 종료된다.") void checkCommandEnd() { // given - final MoveController moveController = new MoveController(new ChessGame(), CampType.WHITE); + final MoveController moveController = new MoveController(1L, chessGameService); final Command command = new Command(CommandType.END, List.of("end")); // when - Controller controller = moveController.checkCommand(command, () -> { - }); + Controller controller = moveController.checkCommand(command); // then assertThat(controller) @@ -53,12 +61,11 @@ void checkCommandEnd() { @DisplayName(value = "게임이 움직임 상태일 때 status를 입력하면 게임 결과를 출력하도록 제어한다.") void checkCommandStatus() { // given - final MoveController moveController = new MoveController(new ChessGame(), CampType.WHITE); + final MoveController moveController = new MoveController(1L, chessGameService); final Command command = new Command(CommandType.STATUS, List.of("status")); // when - Controller controller = moveController.checkCommand(command, () -> { - }); + Controller controller = moveController.checkCommand(command); // then assertThat(controller) @@ -70,41 +77,20 @@ void checkCommandStatus() { @ValueSource(strings = {"move", "move a2", "", " move ", "move a2 a3 a5", "move a2a3"}) void checkCommandValidate(final String commands) { // given - final MoveController moveController = new MoveController(new ChessGame(), CampType.WHITE); + final MoveController moveController = new MoveController(1L, chessGameService); final Command command = new Command(CommandType.MOVE, Arrays.asList(commands.split(" "))); // when, then - assertThatThrownBy(() -> moveController.checkCommand(command, () -> { - })) + assertThatThrownBy(() -> moveController.checkCommand(command)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("'move source위치 target위치 - 예. move b2 b3'와 같은 형태로 입력해 주세요."); } - @Test - @DisplayName("게임이 진행 중인 상태가 아니라면 end 상태로 변경한다.") - void move() { - // given - final Command command = new Command(CommandType.MOVE, List.of("move", "b2", "b4")); - final ChessGame chessGame = new ChessGame(); - final CampType campType = CampType.WHITE; - chessGame.run(new Position(1, 0), new Position(3, 0), campType); - ChessGameHelper.playKingDie(chessGame); - final MoveController moveController = new MoveController(chessGame, campType); - - // when - Controller controller = moveController.move(command, () -> { - }); - - // then - assertThat(controller) - .isInstanceOf(EndController.class); - } - @Test @DisplayName(value = "게임이 움직임 상태일 때 실행 중인지 체크하면 true 반환한다") void isRun() { // given - final MoveController moveController = new MoveController(new ChessGame(), CampType.WHITE); + final MoveController moveController = new MoveController(1L, chessGameService); // when boolean isRun = moveController.isRun(); diff --git a/src/test/java/chess/service/ChessBoardHelper.java b/src/test/java/chess/service/ChessBoardHelper.java index e9c4d2c0773..04748c70fbf 100644 --- a/src/test/java/chess/service/ChessBoardHelper.java +++ b/src/test/java/chess/service/ChessBoardHelper.java @@ -22,14 +22,7 @@ import static chess.domain.piece.PieceType.ROOK; public final class ChessBoardHelper { - - public static ChessBoard createMockBoard() { - final Map board = new HashMap<>(); - createWhiteArea(board); - createBlackArea(board); - return ChessBoard.create(board); - } - + public static ChessBoard createMockProgressBoard() { final Map board = new HashMap<>(); createWhiteProgressArea(board); @@ -37,33 +30,6 @@ public static ChessBoard createMockProgressBoard() { return ChessBoard.create(board); } - private static void createWhiteArea(final Map board) { - createPieces(board, 0, CampType.WHITE); - createPawnPieces(board, 1, CampType.WHITE); - } - - private static void createBlackArea(final Map board) { - createPawnPieces(board, 6, CampType.BLACK); - createPieces(board, 7, CampType.BLACK); - } - - private static void createPieces(final Map board, final int rank, final CampType campType) { - board.put(new Position(rank, 0), new Piece(ROOK, campType, new Rook())); - board.put(new Position(rank, 1), new Piece(KNIGHT, campType, new Knight())); - board.put(new Position(rank, 2), new Piece(BISHOP, campType, new Bishop())); - board.put(new Position(rank, 3), new Piece(QUEEN, campType, new Queen())); - board.put(new Position(rank, 4), new Piece(KING, campType, new King())); - board.put(new Position(rank, 5), new Piece(BISHOP, campType, new Bishop())); - board.put(new Position(rank, 6), new Piece(KNIGHT, campType, new Knight())); - board.put(new Position(rank, 7), new Piece(ROOK, campType, new Rook())); - } - - private static void createPawnPieces(final Map board, final int rank, final CampType campType) { - for (int file = 0; file < 8; file++) { - board.put(new Position(rank, file), new Piece(PAWN, campType, new Pawn())); - } - } - private static void createWhiteProgressArea(final Map board) { createProgressPieces(board, 0, CampType.WHITE); createProgressPawnPieces(board, 1, CampType.WHITE); From 1d433e830f7c3dc84fe48bfa816e243a21d6f1dd Mon Sep 17 00:00:00 2001 From: jiwon Date: Mon, 27 Mar 2023 17:04:56 +0900 Subject: [PATCH 65/76] =?UTF-8?q?feat:=20=EC=B2=B4=EC=8A=A4=ED=8C=90=20?= =?UTF-8?q?=EC=B6=9C=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=EC=9D=84=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/ChessApplication.java | 7 ++- .../java/chess/controller/ChessHandler.java | 49 +++++++++++++------ .../chess/controller/status/Controller.java | 4 +- .../controller/status/EndController.java | 6 ++- .../controller/status/StartController.java | 24 ++++++--- .../controller/status/StatusController.java | 27 +++++++--- .../controller/status/EndControllerTest.java | 3 +- .../status/StartControllerTest.java | 32 +++++++----- .../status/StatusControllerTest.java | 34 ++++++++----- 9 files changed, 126 insertions(+), 60 deletions(-) diff --git a/src/main/java/chess/ChessApplication.java b/src/main/java/chess/ChessApplication.java index 03f68f40320..67a98d40d7f 100644 --- a/src/main/java/chess/ChessApplication.java +++ b/src/main/java/chess/ChessApplication.java @@ -1,10 +1,15 @@ package chess; import chess.controller.ChessHandler; +import chess.database.JdbcTemplate; +import chess.database.properties.ChessProperties; +import chess.service.ServiceManager; public final class ChessApplication { public static void main(String[] args) { - final ChessHandler chessHandler = new ChessHandler(); + final ChessProperties chessProperties = new ChessProperties(); + final ServiceManager serviceManager = new ServiceManager(new JdbcTemplate(chessProperties)); + final ChessHandler chessHandler = new ChessHandler(serviceManager); chessHandler.run(); } } diff --git a/src/main/java/chess/controller/ChessHandler.java b/src/main/java/chess/controller/ChessHandler.java index c336cbb031c..25a6c024d0d 100644 --- a/src/main/java/chess/controller/ChessHandler.java +++ b/src/main/java/chess/controller/ChessHandler.java @@ -1,41 +1,60 @@ package chess.controller; -import chess.controller.mapper.ChessBoardDtoMapper; import chess.controller.status.Controller; import chess.controller.status.StartController; -import chess.domain.chess.ChessGame; +import chess.service.ChessGameService; +import chess.service.ServiceManager; +import chess.service.UserService; import chess.view.InputView; import chess.view.OutputView; import java.util.List; +import java.util.function.Supplier; public final class ChessHandler { - public void run() { - OutputView.printStartMessage(); - final ChessGame chessGame = new ChessGame(); - start(chessGame); + private final UserService userService; + private final ChessGameService chessGameService; + + public ChessHandler(final ServiceManager serviceManager) { + this.userService = serviceManager.userService(); + this.chessGameService = serviceManager.chessGameService(); } - private void start(final ChessGame chessGame) { - Controller controller = new StartController(chessGame); + public void run() { + final Long userId = getUserId(); + OutputView.printStartMessage(); + Controller controller = new StartController(userId, chessGameService); while (controller.isRun()) { - controller = play(chessGame, controller); + controller = play(controller); } } - private Controller play(final ChessGame chessGame, Controller controller) { + private Controller play(Controller controller) { try { final List commands = InputView.getCommands(); final Command command = Command.findCommand(commands); - controller = controller.checkCommand(command, - () -> OutputView.printBoard( - ChessBoardDtoMapper.createChessBoardDto(chessGame.getChessBoard()) - )); + controller = controller.checkCommand(command); + controller.printBoard(); return controller; } catch (IllegalArgumentException e) { OutputView.print(e.getMessage()); - return play(chessGame, controller); + return play(controller); + } + } + + private Long getUserId() { + OutputView.printUserNameInputMessage(); + return getUserIdWithRetry(InputView::getCommand); + } + + private Long getUserIdWithRetry(final Supplier supplier) { + try { + final String name = supplier.get(); + return userService.getUserId(name); + } catch (IllegalArgumentException e) { + OutputView.print(e.getMessage()); + return getUserIdWithRetry(supplier); } } } diff --git a/src/main/java/chess/controller/status/Controller.java b/src/main/java/chess/controller/status/Controller.java index accf8df8cd9..7a89d85a583 100644 --- a/src/main/java/chess/controller/status/Controller.java +++ b/src/main/java/chess/controller/status/Controller.java @@ -3,7 +3,9 @@ import chess.controller.Command; public interface Controller { - Controller checkCommand(final Command command, final Runnable runnable); + Controller checkCommand(final Command command); boolean isRun(); + + void printBoard(); } diff --git a/src/main/java/chess/controller/status/EndController.java b/src/main/java/chess/controller/status/EndController.java index b9895681ffc..a7623550ab2 100644 --- a/src/main/java/chess/controller/status/EndController.java +++ b/src/main/java/chess/controller/status/EndController.java @@ -7,7 +7,7 @@ public final class EndController implements Controller { } @Override - public Controller checkCommand(final Command command, final Runnable runnable) { + public Controller checkCommand(final Command command) { throw new IllegalArgumentException("게임이 끝났습니다."); } @@ -15,4 +15,8 @@ public Controller checkCommand(final Command command, final Runnable runnable) { public boolean isRun() { return false; } + + @Override + public void printBoard() { + } } diff --git a/src/main/java/chess/controller/status/StartController.java b/src/main/java/chess/controller/status/StartController.java index fde519d19d7..bc61a1fcaee 100644 --- a/src/main/java/chess/controller/status/StartController.java +++ b/src/main/java/chess/controller/status/StartController.java @@ -1,31 +1,39 @@ package chess.controller.status; import chess.controller.Command; -import chess.domain.chess.CampType; +import chess.controller.mapper.ChessBoardDtoMapper; import chess.domain.chess.ChessGame; +import chess.service.ChessGameService; +import chess.view.OutputView; public final class StartController implements Controller { + private final Long userId; + private final ChessGameService chessGameService; - private final ChessGame chessGame; - - public StartController(final ChessGame chessGame) { - this.chessGame = chessGame; + public StartController(final Long userId, final ChessGameService chessGameService) { + this.userId = userId; + this.chessGameService = chessGameService; } @Override - public Controller checkCommand(final Command command, final Runnable runnable) { + public Controller checkCommand(final Command command) { if (command.isEnd()) { return new EndController(); } if (!command.isStart()) { throw new IllegalArgumentException("게임이 시작되지 않았습니다."); } - runnable.run(); - return new MoveController(chessGame, CampType.WHITE); + return new MoveController(userId, chessGameService); } @Override public boolean isRun() { return true; } + + @Override + public void printBoard() { + ChessGame chessGame = chessGameService.getChessGame(userId); + OutputView.printBoard(ChessBoardDtoMapper.createChessBoardDto(chessGame.getChessBoard())); + } } diff --git a/src/main/java/chess/controller/status/StatusController.java b/src/main/java/chess/controller/status/StatusController.java index 4fdaf474acd..8929f02a7cd 100644 --- a/src/main/java/chess/controller/status/StatusController.java +++ b/src/main/java/chess/controller/status/StatusController.java @@ -2,23 +2,27 @@ import chess.controller.Command; import chess.controller.dto.ChessResultDto; +import chess.controller.mapper.ChessBoardDtoMapper; import chess.controller.mapper.ChessResultDtoMapper; -import chess.domain.chess.CampType; import chess.domain.chess.ChessGame; import chess.domain.chess.ChessGameCalculator; +import chess.domain.chess.vo.ScoreVO; +import chess.service.ChessGameService; import chess.view.OutputView; public final class StatusController implements Controller { + private final Long userId; private final ChessGame chessGame; - private final CampType campType; + private final ChessGameService chessGameService; - StatusController(final ChessGame chessGame, final CampType campType) { - this.chessGame = chessGame; - this.campType = campType; + StatusController(final Long userId, final ChessGameService chessGameService) { + this.userId = userId; + this.chessGame = chessGameService.getChessGame(userId); + this.chessGameService = chessGameService; } @Override - public Controller checkCommand(final Command command, final Runnable runnable) { + public Controller checkCommand(final Command command) { if (command.isStart()) { throw new IllegalArgumentException("이미 시작이 완료되었습니다."); } @@ -26,7 +30,7 @@ public Controller checkCommand(final Command command, final Runnable runnable) { return new EndController(); } if (command.isMove()) { - return new MoveController(chessGame, campType).move(command, runnable); + return new MoveController(userId, chessGameService).move(command); } return getStatus(true); } @@ -36,10 +40,16 @@ public boolean isRun() { return true; } + @Override + public void printBoard() { + OutputView.printBoard(ChessBoardDtoMapper.createChessBoardDto(chessGame.getChessBoard())); + } + Controller getStatus(final boolean isGameRun) { if (!isGameRun) { OutputView.print("킹이 사망하여 게임이 종료되었습니다!"); runCalculator().run(); + chessGameService.clear(userId); return new EndController(); } runCalculator().run(); @@ -48,7 +58,8 @@ Controller getStatus(final boolean isGameRun) { private Runnable runCalculator() { return () -> { - ChessResultDto chessResultDto = ChessResultDtoMapper.from(ChessGameCalculator.calculate(chessGame)); + final ScoreVO chessResult = ChessGameCalculator.calculate(chessGame); + final ChessResultDto chessResultDto = ChessResultDtoMapper.from(chessResult); OutputView.printChessResult(chessResultDto); }; } diff --git a/src/test/java/chess/controller/status/EndControllerTest.java b/src/test/java/chess/controller/status/EndControllerTest.java index bf1d76fe4bb..c486fd52cb8 100644 --- a/src/test/java/chess/controller/status/EndControllerTest.java +++ b/src/test/java/chess/controller/status/EndControllerTest.java @@ -20,8 +20,7 @@ void checkCommand() { final Command command = new Command(CommandType.END, List.of("end")); // when, then - assertThatThrownBy(() -> endController.checkCommand(command, () -> { - })) + assertThatThrownBy(() -> endController.checkCommand(command)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("게임이 끝났습니다."); } diff --git a/src/test/java/chess/controller/status/StartControllerTest.java b/src/test/java/chess/controller/status/StartControllerTest.java index 8a22926f762..41f5cf82171 100644 --- a/src/test/java/chess/controller/status/StartControllerTest.java +++ b/src/test/java/chess/controller/status/StartControllerTest.java @@ -2,26 +2,38 @@ import chess.controller.Command; import chess.controller.CommandType; -import chess.domain.chess.ChessGame; +import chess.service.ChessGameService; +import chess.service.MockServiceManager; +import chess.service.Service; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class StartControllerTest { + private ChessGameService chessGameService; + + @BeforeAll + void init() { + final Service mockServiceManager = new MockServiceManager(); + chessGameService = mockServiceManager.chessGameService(); + } + @DisplayName(value = "게임이 시작 상태일 때 사용자가 입력한 명령어가 move면 예외가 발생한다.") void checkCommandMove() { // given - final StartController startController = new StartController(new ChessGame()); + final StartController startController = new StartController(1L, chessGameService); final Command command = new Command(CommandType.MOVE, List.of("move a2")); // when, then - assertThatThrownBy(() -> startController.checkCommand(command, () -> { - })) + assertThatThrownBy(() -> startController.checkCommand(command)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("게임이 시작되지 않았습니다."); } @@ -29,12 +41,11 @@ void checkCommandMove() { @DisplayName(value = "게임이 시작 상태일 때 사용자가 입력한 명령어가 status면 예외가 발생한다.") void checkCommandStatus() { // given - final StartController startController = new StartController(new ChessGame()); + final StartController startController = new StartController(1L, chessGameService); final Command command = new Command(CommandType.STATUS, List.of("status")); // when, then - assertThatThrownBy(() -> startController.checkCommand(command, () -> { - })) + assertThatThrownBy(() -> startController.checkCommand(command)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("게임이 시작되지 않았습니다."); } @@ -43,12 +54,11 @@ void checkCommandStatus() { @DisplayName(value = "게임이 시작 상태일 때 사용자가 입력한 명령어가 end면 게임이 종료된다.") void checkCommandEnd() { // given - final StartController startController = new StartController(new ChessGame()); + final StartController startController = new StartController(1L, chessGameService); final Command command = new Command(CommandType.END, List.of("end")); // when - Controller controller = startController.checkCommand(command, () -> { - }); + Controller controller = startController.checkCommand(command); // then assertThat(controller) @@ -59,7 +69,7 @@ void checkCommandEnd() { @DisplayName(value = "게임이 시작 상태일 때 실행 중인지 체크하면 true를 반환한다") void isRun() { // given - final StartController startController = new StartController(new ChessGame()); + final StartController startController = new StartController(1L, chessGameService); // when boolean isRun = startController.isRun(); diff --git a/src/test/java/chess/controller/status/StatusControllerTest.java b/src/test/java/chess/controller/status/StatusControllerTest.java index acf10d74874..cde1ed21298 100644 --- a/src/test/java/chess/controller/status/StatusControllerTest.java +++ b/src/test/java/chess/controller/status/StatusControllerTest.java @@ -2,28 +2,38 @@ import chess.controller.Command; import chess.controller.CommandType; -import chess.domain.chess.CampType; -import chess.domain.chess.ChessGame; +import chess.service.ChessGameService; +import chess.service.MockServiceManager; +import chess.service.Service; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class StatusControllerTest { + private ChessGameService chessGameService; + + @BeforeAll + void init() { + final Service mockServiceManager = new MockServiceManager(); + chessGameService = mockServiceManager.chessGameService(); + } @Test @DisplayName(value = "게임이 status 상태일 때 start를 입력하면 예외가 발생한다.") void checkCommandStart() { // given - final StatusController statusController = new StatusController(new ChessGame(), CampType.WHITE); + final StatusController statusController = new StatusController(1L, chessGameService); final Command command = new Command(CommandType.START, List.of("start")); // when, then - assertThatThrownBy(() -> statusController.checkCommand(command, () -> { - })) + assertThatThrownBy(() -> statusController.checkCommand(command)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("이미 시작이 완료되었습니다."); } @@ -32,12 +42,11 @@ void checkCommandStart() { @DisplayName(value = "게임이 status 상태일 때 end를 입력하면 게임이 종료된다.") void checkCommandEnd() { // given - final StatusController statusController = new StatusController(new ChessGame(), CampType.WHITE); + final StatusController statusController = new StatusController(1L, chessGameService); final Command command = new Command(CommandType.END, List.of("end")); // when - Controller controller = statusController.checkCommand(command, () -> { - }); + Controller controller = statusController.checkCommand(command); // then assertThat(controller) @@ -48,12 +57,11 @@ void checkCommandEnd() { @DisplayName(value = "게임이 status 상태일 때 move를 입력하면 이동하도록 제어한다.") void checkCommandMove() { // given - final StatusController statusController = new StatusController(new ChessGame(), CampType.WHITE); + final StatusController statusController = new StatusController(1L, chessGameService); final Command command = new Command(CommandType.MOVE, List.of("move", "a2", "a4")); // when - Controller controller = statusController.checkCommand(command, () -> { - }); + Controller controller = statusController.checkCommand(command); // then assertThat(controller) @@ -64,7 +72,7 @@ void checkCommandMove() { @DisplayName(value = "게임이 status 상태일 때 실행 중인지 체크하면 true를 반환한다") void isRun() { // given - final StatusController statusController = new StatusController(new ChessGame(), CampType.WHITE); + final StatusController statusController = new StatusController(1L, chessGameService); // when boolean isRun = statusController.isRun(); @@ -78,7 +86,7 @@ void isRun() { @DisplayName("게임이 진행 중인 상태가 아니라면 end 상태로 변경한다.") void getStatus() { // given - final StatusController statusController = new StatusController(new ChessGame(), CampType.WHITE); + final StatusController statusController = new StatusController(1L, chessGameService); // when Controller controller = statusController.getStatus(false); From 7129d4a6050d0de810b1b6fdf794843ade359569 Mon Sep 17 00:00:00 2001 From: jiwon Date: Thu, 30 Mar 2023 20:09:14 +0900 Subject: [PATCH 66/76] =?UTF-8?q?refactor:=20ScoreVO=EC=99=80=20Service=20?= =?UTF-8?q?=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=EC=9D=98=20?= =?UTF-8?q?=EB=84=A4=EC=9D=B4=EB=B0=8D=EC=9D=84=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chess/controller/mapper/ChessResultDtoMapper.java | 6 +++--- .../java/chess/controller/status/StatusController.java | 4 ++-- src/main/java/chess/domain/chess/ChessGameCalculator.java | 6 +++--- .../domain/chess/vo/{ScoreVO.java => ChessScore.java} | 8 ++++---- .../chess/service/{Service.java => ServiceHandler.java} | 2 +- src/main/java/chess/service/ServiceManager.java | 2 +- .../java/chess/controller/status/MoveControllerTest.java | 8 ++++---- .../java/chess/controller/status/StartControllerTest.java | 8 ++++---- .../chess/controller/status/StatusControllerTest.java | 8 ++++---- .../java/chess/domain/chess/ChessGameCalculatorTest.java | 6 +++--- ...ServiceTest.java => ChessBoardServiceTestHandler.java} | 2 +- ...eServiceTest.java => ChessGameServiceTestHandler.java} | 2 +- ...ServiceManager.java => MockServiceManagerHandler.java} | 2 +- .../{UserServiceTest.java => UserServiceTestHandler.java} | 2 +- 14 files changed, 33 insertions(+), 33 deletions(-) rename src/main/java/chess/domain/chess/vo/{ScoreVO.java => ChessScore.java} (70%) rename src/main/java/chess/service/{Service.java => ServiceHandler.java} (74%) rename src/test/java/chess/service/{ChessBoardServiceTest.java => ChessBoardServiceTestHandler.java} (99%) rename src/test/java/chess/service/{ChessGameServiceTest.java => ChessGameServiceTestHandler.java} (99%) rename src/test/java/chess/service/{MockServiceManager.java => MockServiceManagerHandler.java} (88%) rename src/test/java/chess/service/{UserServiceTest.java => UserServiceTestHandler.java} (97%) diff --git a/src/main/java/chess/controller/mapper/ChessResultDtoMapper.java b/src/main/java/chess/controller/mapper/ChessResultDtoMapper.java index 2c8383bbdd8..68fde7cf387 100644 --- a/src/main/java/chess/controller/mapper/ChessResultDtoMapper.java +++ b/src/main/java/chess/controller/mapper/ChessResultDtoMapper.java @@ -1,10 +1,10 @@ package chess.controller.mapper; import chess.controller.dto.ChessResultDto; -import chess.domain.chess.vo.ScoreVO; +import chess.domain.chess.vo.ChessScore; public class ChessResultDtoMapper { - public static ChessResultDto from(final ScoreVO scoreVO) { - return new ChessResultDto(scoreVO.getWhiteScore().getScore(), scoreVO.getBlackScore().getScore()); + public static ChessResultDto from(final ChessScore chessScore) { + return new ChessResultDto(chessScore.getWhiteScore().getScore(), chessScore.getBlackScore().getScore()); } } diff --git a/src/main/java/chess/controller/status/StatusController.java b/src/main/java/chess/controller/status/StatusController.java index 8929f02a7cd..982125bdb18 100644 --- a/src/main/java/chess/controller/status/StatusController.java +++ b/src/main/java/chess/controller/status/StatusController.java @@ -6,7 +6,7 @@ import chess.controller.mapper.ChessResultDtoMapper; import chess.domain.chess.ChessGame; import chess.domain.chess.ChessGameCalculator; -import chess.domain.chess.vo.ScoreVO; +import chess.domain.chess.vo.ChessScore; import chess.service.ChessGameService; import chess.view.OutputView; @@ -58,7 +58,7 @@ Controller getStatus(final boolean isGameRun) { private Runnable runCalculator() { return () -> { - final ScoreVO chessResult = ChessGameCalculator.calculate(chessGame); + final ChessScore chessResult = ChessGameCalculator.calculate(chessGame); final ChessResultDto chessResultDto = ChessResultDtoMapper.from(chessResult); OutputView.printChessResult(chessResultDto); }; diff --git a/src/main/java/chess/domain/chess/ChessGameCalculator.java b/src/main/java/chess/domain/chess/ChessGameCalculator.java index b02bdf6c1d9..10f19116206 100644 --- a/src/main/java/chess/domain/chess/ChessGameCalculator.java +++ b/src/main/java/chess/domain/chess/ChessGameCalculator.java @@ -1,6 +1,6 @@ package chess.domain.chess; -import chess.domain.chess.vo.ScoreVO; +import chess.domain.chess.vo.ChessScore; import chess.domain.piece.Piece; import chess.domain.piece.Score; import chess.domain.piece.move.Position; @@ -15,14 +15,14 @@ public final class ChessGameCalculator { private static final int PAWN_SUBTRACT_COUNT_THRESHOLD = 1; private static final Score PAWN_SPECIAL_SCORE = Score.create(0.5); - public static ScoreVO calculate(final ChessGame chessGame) { + public static ChessScore calculate(final ChessGame chessGame) { final Map whiteBoard = chessGame.getWhiteBoard(); Score whiteScore = calculateScore(whiteBoard); final Map blackBoard = chessGame.getBlackBoard(); Score blackScore = calculateScore(blackBoard); - return new ScoreVO(whiteScore, blackScore); + return new ChessScore(whiteScore, blackScore); } private static Score calculateScore(Map board) { diff --git a/src/main/java/chess/domain/chess/vo/ScoreVO.java b/src/main/java/chess/domain/chess/vo/ChessScore.java similarity index 70% rename from src/main/java/chess/domain/chess/vo/ScoreVO.java rename to src/main/java/chess/domain/chess/vo/ChessScore.java index 424eccc9fcf..f0ccd5100f2 100644 --- a/src/main/java/chess/domain/chess/vo/ScoreVO.java +++ b/src/main/java/chess/domain/chess/vo/ChessScore.java @@ -4,11 +4,11 @@ import java.util.Objects; -public class ScoreVO { +public class ChessScore { private final Score whiteScore; private final Score blackScore; - public ScoreVO(final Score whiteScore, final Score blackScore) { + public ChessScore(final Score whiteScore, final Score blackScore) { this.whiteScore = whiteScore; this.blackScore = blackScore; } @@ -17,8 +17,8 @@ public ScoreVO(final Score whiteScore, final Score blackScore) { public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - final ScoreVO scoreVO = (ScoreVO) o; - return Objects.equals(whiteScore, scoreVO.whiteScore) && Objects.equals(blackScore, scoreVO.blackScore); + final ChessScore chessScore = (ChessScore) o; + return Objects.equals(whiteScore, chessScore.whiteScore) && Objects.equals(blackScore, chessScore.blackScore); } @Override diff --git a/src/main/java/chess/service/Service.java b/src/main/java/chess/service/ServiceHandler.java similarity index 74% rename from src/main/java/chess/service/Service.java rename to src/main/java/chess/service/ServiceHandler.java index 255e6d22aeb..875120b24c6 100644 --- a/src/main/java/chess/service/Service.java +++ b/src/main/java/chess/service/ServiceHandler.java @@ -1,6 +1,6 @@ package chess.service; -public interface Service { +public interface ServiceHandler { UserService userService(); ChessGameService chessGameService(); diff --git a/src/main/java/chess/service/ServiceManager.java b/src/main/java/chess/service/ServiceManager.java index 612993407b1..ac831df19ba 100644 --- a/src/main/java/chess/service/ServiceManager.java +++ b/src/main/java/chess/service/ServiceManager.java @@ -7,7 +7,7 @@ import chess.dao.user.UserDaoImpl; import chess.database.JdbcTemplate; -public final class ServiceManager implements Service { +public final class ServiceManager implements ServiceHandler { private final JdbcTemplate jdbcTemplate; public ServiceManager(final JdbcTemplate jdbcTemplate) { diff --git a/src/test/java/chess/controller/status/MoveControllerTest.java b/src/test/java/chess/controller/status/MoveControllerTest.java index 05d5374461a..c32643a6ca6 100644 --- a/src/test/java/chess/controller/status/MoveControllerTest.java +++ b/src/test/java/chess/controller/status/MoveControllerTest.java @@ -3,8 +3,8 @@ import chess.controller.Command; import chess.controller.CommandType; import chess.service.ChessGameService; -import chess.service.MockServiceManager; -import chess.service.Service; +import chess.service.MockServiceManagerHandler; +import chess.service.ServiceHandler; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -25,8 +25,8 @@ class MoveControllerTest { @BeforeAll void init() { - final Service mockServiceManager = new MockServiceManager(); - chessGameService = mockServiceManager.chessGameService(); + final ServiceHandler mockServiceManagerHandler = new MockServiceManagerHandler(); + chessGameService = mockServiceManagerHandler.chessGameService(); } @Test diff --git a/src/test/java/chess/controller/status/StartControllerTest.java b/src/test/java/chess/controller/status/StartControllerTest.java index 41f5cf82171..2f2850d93a6 100644 --- a/src/test/java/chess/controller/status/StartControllerTest.java +++ b/src/test/java/chess/controller/status/StartControllerTest.java @@ -3,8 +3,8 @@ import chess.controller.Command; import chess.controller.CommandType; import chess.service.ChessGameService; -import chess.service.MockServiceManager; -import chess.service.Service; +import chess.service.MockServiceManagerHandler; +import chess.service.ServiceHandler; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -22,8 +22,8 @@ class StartControllerTest { @BeforeAll void init() { - final Service mockServiceManager = new MockServiceManager(); - chessGameService = mockServiceManager.chessGameService(); + final ServiceHandler mockServiceManagerHandler = new MockServiceManagerHandler(); + chessGameService = mockServiceManagerHandler.chessGameService(); } @DisplayName(value = "게임이 시작 상태일 때 사용자가 입력한 명령어가 move면 예외가 발생한다.") diff --git a/src/test/java/chess/controller/status/StatusControllerTest.java b/src/test/java/chess/controller/status/StatusControllerTest.java index cde1ed21298..8faa747f9d9 100644 --- a/src/test/java/chess/controller/status/StatusControllerTest.java +++ b/src/test/java/chess/controller/status/StatusControllerTest.java @@ -3,8 +3,8 @@ import chess.controller.Command; import chess.controller.CommandType; import chess.service.ChessGameService; -import chess.service.MockServiceManager; -import chess.service.Service; +import chess.service.MockServiceManagerHandler; +import chess.service.ServiceHandler; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -21,8 +21,8 @@ public class StatusControllerTest { @BeforeAll void init() { - final Service mockServiceManager = new MockServiceManager(); - chessGameService = mockServiceManager.chessGameService(); + final ServiceHandler mockServiceManagerHandler = new MockServiceManagerHandler(); + chessGameService = mockServiceManagerHandler.chessGameService(); } @Test diff --git a/src/test/java/chess/domain/chess/ChessGameCalculatorTest.java b/src/test/java/chess/domain/chess/ChessGameCalculatorTest.java index b6f89ef17bc..d3bac7e0fcd 100644 --- a/src/test/java/chess/domain/chess/ChessGameCalculatorTest.java +++ b/src/test/java/chess/domain/chess/ChessGameCalculatorTest.java @@ -1,6 +1,6 @@ package chess.domain.chess; -import chess.domain.chess.vo.ScoreVO; +import chess.domain.chess.vo.ChessScore; import chess.domain.piece.Score; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -14,10 +14,10 @@ class ChessGameCalculatorTest { void calculate() { // given final ChessGame chessGame = new ChessGame(CampType.WHITE); - final ScoreVO expected = new ScoreVO(Score.create(38.0), Score.create(38.0)); + final ChessScore expected = new ChessScore(Score.create(38.0), Score.create(38.0)); // when - ScoreVO actual = ChessGameCalculator.calculate(chessGame); + ChessScore actual = ChessGameCalculator.calculate(chessGame); // then assertThat(actual) diff --git a/src/test/java/chess/service/ChessBoardServiceTest.java b/src/test/java/chess/service/ChessBoardServiceTestHandler.java similarity index 99% rename from src/test/java/chess/service/ChessBoardServiceTest.java rename to src/test/java/chess/service/ChessBoardServiceTestHandler.java index 00993e1d58a..d8686f31673 100644 --- a/src/test/java/chess/service/ChessBoardServiceTest.java +++ b/src/test/java/chess/service/ChessBoardServiceTestHandler.java @@ -20,7 +20,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -class ChessBoardServiceTest { +class ChessBoardServiceTestHandler { @Test @DisplayName("체스 게임 아이디로 체스판 정보를 조회한다.") diff --git a/src/test/java/chess/service/ChessGameServiceTest.java b/src/test/java/chess/service/ChessGameServiceTestHandler.java similarity index 99% rename from src/test/java/chess/service/ChessGameServiceTest.java rename to src/test/java/chess/service/ChessGameServiceTestHandler.java index 69f62af3b63..b632251c8c8 100644 --- a/src/test/java/chess/service/ChessGameServiceTest.java +++ b/src/test/java/chess/service/ChessGameServiceTestHandler.java @@ -16,7 +16,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -class ChessGameServiceTest { +class ChessGameServiceTestHandler { @Test @DisplayName("사용자의 아이디에 해당하는 체스 게임이 존재하지 않으면 새 게임을 반환한다.") diff --git a/src/test/java/chess/service/MockServiceManager.java b/src/test/java/chess/service/MockServiceManagerHandler.java similarity index 88% rename from src/test/java/chess/service/MockServiceManager.java rename to src/test/java/chess/service/MockServiceManagerHandler.java index 2d189a3c91b..e802997e878 100644 --- a/src/test/java/chess/service/MockServiceManager.java +++ b/src/test/java/chess/service/MockServiceManagerHandler.java @@ -4,7 +4,7 @@ import chess.dao.chess.MockPieceDao; import chess.dao.user.MockUserDao; -public class MockServiceManager implements Service { +public class MockServiceManagerHandler implements ServiceHandler { @Override public UserService userService() { return new UserService(new MockUserDao()); diff --git a/src/test/java/chess/service/UserServiceTest.java b/src/test/java/chess/service/UserServiceTestHandler.java similarity index 97% rename from src/test/java/chess/service/UserServiceTest.java rename to src/test/java/chess/service/UserServiceTestHandler.java index 1b81a5e13bc..4acb520774a 100644 --- a/src/test/java/chess/service/UserServiceTest.java +++ b/src/test/java/chess/service/UserServiceTestHandler.java @@ -6,7 +6,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -class UserServiceTest { +class UserServiceTestHandler { @Test @DisplayName("사용자의 이름이 이미 저장되어 있다면, 존재하는 사용자의 아이디를 반환한다.") From 4c2ccfbcbfd85852c66e249dd54808048cddfa06 Mon Sep 17 00:00:00 2001 From: jiwon Date: Thu, 30 Mar 2023 20:13:26 +0900 Subject: [PATCH 67/76] =?UTF-8?q?feat:=20=EC=B2=B4=EC=8A=A4=ED=8C=90?= =?UTF-8?q?=EC=9D=98=20=EC=B6=9C=EB=A0=A5=20=EA=B8=B0=EB=8A=A5=EC=9D=84=20?= =?UTF-8?q?=ED=95=B8=EB=93=A4=EB=9F=AC=EC=97=90=EA=B2=8C=20=EC=9C=84?= =?UTF-8?q?=EC=9E=84=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/controller/ChessHandler.java | 7 ++++++- src/main/java/chess/controller/status/Controller.java | 5 ++++- .../java/chess/controller/status/EndController.java | 6 +++++- .../java/chess/controller/status/MoveController.java | 7 +++---- .../java/chess/controller/status/StartController.java | 10 +++++----- .../java/chess/controller/status/StatusController.java | 7 ++++--- 6 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/main/java/chess/controller/ChessHandler.java b/src/main/java/chess/controller/ChessHandler.java index 25a6c024d0d..c611d68d096 100644 --- a/src/main/java/chess/controller/ChessHandler.java +++ b/src/main/java/chess/controller/ChessHandler.java @@ -1,7 +1,9 @@ package chess.controller; +import chess.controller.mapper.ChessBoardDtoMapper; import chess.controller.status.Controller; import chess.controller.status.StartController; +import chess.domain.chess.ChessGame; import chess.service.ChessGameService; import chess.service.ServiceManager; import chess.service.UserService; @@ -9,6 +11,7 @@ import chess.view.OutputView; import java.util.List; +import java.util.Optional; import java.util.function.Supplier; public final class ChessHandler { @@ -35,7 +38,9 @@ private Controller play(Controller controller) { final List commands = InputView.getCommands(); final Command command = Command.findCommand(commands); controller = controller.checkCommand(command); - controller.printBoard(); + final Optional chessGame = controller.findGame(); + chessGame.ifPresent(game -> + OutputView.printBoard(ChessBoardDtoMapper.createChessBoardDto(game.getChessBoard()))); return controller; } catch (IllegalArgumentException e) { OutputView.print(e.getMessage()); diff --git a/src/main/java/chess/controller/status/Controller.java b/src/main/java/chess/controller/status/Controller.java index 7a89d85a583..8e65c0385eb 100644 --- a/src/main/java/chess/controller/status/Controller.java +++ b/src/main/java/chess/controller/status/Controller.java @@ -1,11 +1,14 @@ package chess.controller.status; import chess.controller.Command; +import chess.domain.chess.ChessGame; + +import java.util.Optional; public interface Controller { Controller checkCommand(final Command command); boolean isRun(); - void printBoard(); + Optional findGame(); } diff --git a/src/main/java/chess/controller/status/EndController.java b/src/main/java/chess/controller/status/EndController.java index a7623550ab2..38cd6d5fad1 100644 --- a/src/main/java/chess/controller/status/EndController.java +++ b/src/main/java/chess/controller/status/EndController.java @@ -1,6 +1,9 @@ package chess.controller.status; import chess.controller.Command; +import chess.domain.chess.ChessGame; + +import java.util.Optional; public final class EndController implements Controller { EndController() { @@ -17,6 +20,7 @@ public boolean isRun() { } @Override - public void printBoard() { + public Optional findGame() { + return Optional.empty(); } } diff --git a/src/main/java/chess/controller/status/MoveController.java b/src/main/java/chess/controller/status/MoveController.java index 76690820537..faeb9776193 100644 --- a/src/main/java/chess/controller/status/MoveController.java +++ b/src/main/java/chess/controller/status/MoveController.java @@ -1,17 +1,16 @@ package chess.controller.status; import chess.controller.Command; -import chess.controller.mapper.ChessBoardDtoMapper; import chess.domain.chess.ChessGame; import chess.domain.piece.Piece; import chess.domain.piece.move.Position; import chess.domain.piece.move.PositionConverter; import chess.entity.PieceEntity; import chess.service.ChessGameService; -import chess.view.OutputView; import java.util.List; import java.util.Map; +import java.util.Optional; public final class MoveController implements Controller { @@ -45,8 +44,8 @@ public boolean isRun() { } @Override - public void printBoard() { - OutputView.printBoard(ChessBoardDtoMapper.createChessBoardDto(chessGame.getChessBoard())); + public Optional findGame() { + return Optional.of(chessGame); } Controller move(final Command command) { diff --git a/src/main/java/chess/controller/status/StartController.java b/src/main/java/chess/controller/status/StartController.java index bc61a1fcaee..0d10300e9f5 100644 --- a/src/main/java/chess/controller/status/StartController.java +++ b/src/main/java/chess/controller/status/StartController.java @@ -1,10 +1,10 @@ package chess.controller.status; import chess.controller.Command; -import chess.controller.mapper.ChessBoardDtoMapper; import chess.domain.chess.ChessGame; import chess.service.ChessGameService; -import chess.view.OutputView; + +import java.util.Optional; public final class StartController implements Controller { private final Long userId; @@ -32,8 +32,8 @@ public boolean isRun() { } @Override - public void printBoard() { - ChessGame chessGame = chessGameService.getChessGame(userId); - OutputView.printBoard(ChessBoardDtoMapper.createChessBoardDto(chessGame.getChessBoard())); + public Optional findGame() { + final ChessGame chessGame = chessGameService.getChessGame(userId); + return Optional.of(chessGame); } } diff --git a/src/main/java/chess/controller/status/StatusController.java b/src/main/java/chess/controller/status/StatusController.java index 982125bdb18..c85aa2802c4 100644 --- a/src/main/java/chess/controller/status/StatusController.java +++ b/src/main/java/chess/controller/status/StatusController.java @@ -2,7 +2,6 @@ import chess.controller.Command; import chess.controller.dto.ChessResultDto; -import chess.controller.mapper.ChessBoardDtoMapper; import chess.controller.mapper.ChessResultDtoMapper; import chess.domain.chess.ChessGame; import chess.domain.chess.ChessGameCalculator; @@ -10,6 +9,8 @@ import chess.service.ChessGameService; import chess.view.OutputView; +import java.util.Optional; + public final class StatusController implements Controller { private final Long userId; private final ChessGame chessGame; @@ -41,8 +42,8 @@ public boolean isRun() { } @Override - public void printBoard() { - OutputView.printBoard(ChessBoardDtoMapper.createChessBoardDto(chessGame.getChessBoard())); + public Optional findGame() { + return Optional.of(chessGame); } Controller getStatus(final boolean isGameRun) { From a35e743a5bda6bfa5a1a0be70faf2c210db01503 Mon Sep 17 00:00:00 2001 From: jiwon Date: Thu, 30 Mar 2023 20:35:45 +0900 Subject: [PATCH 68/76] =?UTF-8?q?feat:=20chessGame=EC=9D=84=20=EC=9D=B8?= =?UTF-8?q?=EC=9E=90=EB=A1=9C=20=EA=B4=80=EB=A6=AC=ED=95=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD=ED=95=9C?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chess/controller/status/MoveController.java | 17 ++++++++--------- .../controller/status/StatusController.java | 4 ++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/main/java/chess/controller/status/MoveController.java b/src/main/java/chess/controller/status/MoveController.java index faeb9776193..d8349d9840d 100644 --- a/src/main/java/chess/controller/status/MoveController.java +++ b/src/main/java/chess/controller/status/MoveController.java @@ -15,12 +15,10 @@ public final class MoveController implements Controller { private final Long userId; - private final ChessGame chessGame; private final ChessGameService chessGameService; MoveController(final Long userId, final ChessGameService chessGameService) { this.userId = userId; - this.chessGame = chessGameService.getChessGame(userId); this.chessGameService = chessGameService; } @@ -45,14 +43,15 @@ public boolean isRun() { @Override public Optional findGame() { + final ChessGame chessGame = chessGameService.getChessGame(userId); return Optional.of(chessGame); } Controller move(final Command command) { validateCommand(command); final List commands = command.getCommands(); - - play(commands); + final ChessGame chessGame = chessGameService.getChessGame(userId); + play(commands, chessGame); if (!chessGame.isKingAlive()) { return new StatusController(userId, chessGameService).getStatus(false); } @@ -65,17 +64,17 @@ private void validateCommand(final Command command) { } } - private void play(final List commands) { + private void play(final List commands, final ChessGame chessGame) { final Position source = PositionConverter.convert(commands.get(1)); final Position target = PositionConverter.convert(commands.get(2)); chessGame.play(source, target); - savePlayInfo(source, target); + savePlayInfo(source, target, chessGame); } - private void savePlayInfo(final Position source, final Position target) { + private void savePlayInfo(final Position source, final Position target, final ChessGame chessGame) { final Long chessGameId = chessGameService.getChessGameId(userId); deletePieces(source, target, chessGameId); - savePieces(target, chessGameId); + savePieces(target, chessGameId, chessGame); chessGameService.updateCurrentCamp(chessGameId, chessGame.getCurrentCamp()); } @@ -85,7 +84,7 @@ private void deletePieces(final Position source, final Position target, final Lo chessGameService.deletePieces(sourcePiece, targetPiece); } - private void savePieces(final Position target, final Long chessGameId) { + private void savePieces(final Position target, final Long chessGameId, final ChessGame chessGame) { final Map chessBoard = chessGame.getChessBoard(); final Piece piece = chessBoard.get(target); final PieceEntity savedPiece = PieceEntity.createWithChessGameId(chessGameId, target.getRank(), diff --git a/src/main/java/chess/controller/status/StatusController.java b/src/main/java/chess/controller/status/StatusController.java index c85aa2802c4..70565d7b63e 100644 --- a/src/main/java/chess/controller/status/StatusController.java +++ b/src/main/java/chess/controller/status/StatusController.java @@ -13,12 +13,10 @@ public final class StatusController implements Controller { private final Long userId; - private final ChessGame chessGame; private final ChessGameService chessGameService; StatusController(final Long userId, final ChessGameService chessGameService) { this.userId = userId; - this.chessGame = chessGameService.getChessGame(userId); this.chessGameService = chessGameService; } @@ -43,6 +41,7 @@ public boolean isRun() { @Override public Optional findGame() { + final ChessGame chessGame = chessGameService.getChessGame(userId); return Optional.of(chessGame); } @@ -59,6 +58,7 @@ Controller getStatus(final boolean isGameRun) { private Runnable runCalculator() { return () -> { + final ChessGame chessGame = chessGameService.getChessGame(userId); final ChessScore chessResult = ChessGameCalculator.calculate(chessGame); final ChessResultDto chessResultDto = ChessResultDtoMapper.from(chessResult); OutputView.printChessResult(chessResultDto); From 87453496762e31c1002f5ecd2ff34eab29691172 Mon Sep 17 00:00:00 2001 From: jiwon Date: Thu, 30 Mar 2023 20:56:35 +0900 Subject: [PATCH 69/76] =?UTF-8?q?refactor:=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=9C=20=EB=84=A4=EC=9D=B4=EB=B0=8D?= =?UTF-8?q?=EC=9D=84=20=EB=B3=80=EA=B2=BD=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/controller/ChessHandler.java | 2 +- .../chess/controller/status/MoveController.java | 4 ++-- .../chess/controller/status/StartController.java | 2 +- .../chess/controller/status/StatusController.java | 4 ++-- src/main/java/chess/service/ChessGameService.java | 2 +- src/main/java/chess/service/UserService.java | 2 +- .../chess/service/ChessGameServiceTestHandler.java | 14 +++++++------- .../java/chess/service/UserServiceTestHandler.java | 8 ++++---- 8 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/main/java/chess/controller/ChessHandler.java b/src/main/java/chess/controller/ChessHandler.java index c611d68d096..817ad481844 100644 --- a/src/main/java/chess/controller/ChessHandler.java +++ b/src/main/java/chess/controller/ChessHandler.java @@ -56,7 +56,7 @@ private Long getUserId() { private Long getUserIdWithRetry(final Supplier supplier) { try { final String name = supplier.get(); - return userService.getUserId(name); + return userService.getOrCreateUserId(name); } catch (IllegalArgumentException e) { OutputView.print(e.getMessage()); return getUserIdWithRetry(supplier); diff --git a/src/main/java/chess/controller/status/MoveController.java b/src/main/java/chess/controller/status/MoveController.java index d8349d9840d..800763ecd5f 100644 --- a/src/main/java/chess/controller/status/MoveController.java +++ b/src/main/java/chess/controller/status/MoveController.java @@ -43,14 +43,14 @@ public boolean isRun() { @Override public Optional findGame() { - final ChessGame chessGame = chessGameService.getChessGame(userId); + final ChessGame chessGame = chessGameService.getOrCreateChessGame(userId); return Optional.of(chessGame); } Controller move(final Command command) { validateCommand(command); final List commands = command.getCommands(); - final ChessGame chessGame = chessGameService.getChessGame(userId); + final ChessGame chessGame = chessGameService.getOrCreateChessGame(userId); play(commands, chessGame); if (!chessGame.isKingAlive()) { return new StatusController(userId, chessGameService).getStatus(false); diff --git a/src/main/java/chess/controller/status/StartController.java b/src/main/java/chess/controller/status/StartController.java index 0d10300e9f5..9e15ea8e7b0 100644 --- a/src/main/java/chess/controller/status/StartController.java +++ b/src/main/java/chess/controller/status/StartController.java @@ -33,7 +33,7 @@ public boolean isRun() { @Override public Optional findGame() { - final ChessGame chessGame = chessGameService.getChessGame(userId); + final ChessGame chessGame = chessGameService.getOrCreateChessGame(userId); return Optional.of(chessGame); } } diff --git a/src/main/java/chess/controller/status/StatusController.java b/src/main/java/chess/controller/status/StatusController.java index 70565d7b63e..68c413ab74a 100644 --- a/src/main/java/chess/controller/status/StatusController.java +++ b/src/main/java/chess/controller/status/StatusController.java @@ -41,7 +41,7 @@ public boolean isRun() { @Override public Optional findGame() { - final ChessGame chessGame = chessGameService.getChessGame(userId); + final ChessGame chessGame = chessGameService.getOrCreateChessGame(userId); return Optional.of(chessGame); } @@ -58,7 +58,7 @@ Controller getStatus(final boolean isGameRun) { private Runnable runCalculator() { return () -> { - final ChessGame chessGame = chessGameService.getChessGame(userId); + final ChessGame chessGame = chessGameService.getOrCreateChessGame(userId); final ChessScore chessResult = ChessGameCalculator.calculate(chessGame); final ChessResultDto chessResultDto = ChessResultDtoMapper.from(chessResult); OutputView.printChessResult(chessResultDto); diff --git a/src/main/java/chess/service/ChessGameService.java b/src/main/java/chess/service/ChessGameService.java index 5f0d03f0115..d6680383869 100644 --- a/src/main/java/chess/service/ChessGameService.java +++ b/src/main/java/chess/service/ChessGameService.java @@ -18,7 +18,7 @@ public ChessGameService(final ChessGameDao chessGameDao, final ChessBoardService this.chessBoardService = chessBoardService; } - public ChessGame getChessGame(final Long userId) { + public ChessGame getOrCreateChessGame(final Long userId) { final Optional findChessGameEntity = chessGameDao.findByUserId(userId); if (findChessGameEntity.isEmpty()) { return getNewChessGame(userId); diff --git a/src/main/java/chess/service/UserService.java b/src/main/java/chess/service/UserService.java index 6f67bf65667..0092b92bacb 100644 --- a/src/main/java/chess/service/UserService.java +++ b/src/main/java/chess/service/UserService.java @@ -13,7 +13,7 @@ public UserService(final UserDao userDao) { this.userDao = userDao; } - public Long getUserId(final String name) { + public Long getOrCreateUserId(final String name) { final User user = User.create(name); final String userName = user.getName(); final Optional userEntity = userDao.findByName(userName); diff --git a/src/test/java/chess/service/ChessGameServiceTestHandler.java b/src/test/java/chess/service/ChessGameServiceTestHandler.java index b632251c8c8..cd3c813a9fc 100644 --- a/src/test/java/chess/service/ChessGameServiceTestHandler.java +++ b/src/test/java/chess/service/ChessGameServiceTestHandler.java @@ -20,7 +20,7 @@ class ChessGameServiceTestHandler { @Test @DisplayName("사용자의 아이디에 해당하는 체스 게임이 존재하지 않으면 새 게임을 반환한다.") - void getChessGame_empty() { + void getOrCreateChessGame_empty() { // given final MockChessGameDao chessGameDao = new MockChessGameDao(); final ChessGameService chessGameService = new ChessGameService( @@ -28,7 +28,7 @@ void getChessGame_empty() { final ChessGame expected = new ChessGame(CampType.WHITE); // when - final ChessGame actual = chessGameService.getChessGame(2L); + final ChessGame actual = chessGameService.getOrCreateChessGame(2L); // then assertThat(actual) @@ -37,7 +37,7 @@ void getChessGame_empty() { @Test @DisplayName("사용자의 아이디에 해당하는 체스 게임이 존재하면 해당 게임을 반환한다.") - void getChessGame() { + void getOrCreateChessGame() { // given final Long userId = 1L; final ChessGameService chessGameService = getChessGameService(userId); @@ -45,7 +45,7 @@ void getChessGame() { final ChessGame expected = new ChessGame(mockProgressBoard, CampType.WHITE); // when - final ChessGame actual = chessGameService.getChessGame(userId); + final ChessGame actual = chessGameService.getOrCreateChessGame(userId); // then assertThat(actual) @@ -96,7 +96,7 @@ void updateCurrentCamp() { chessGameService.updateCurrentCamp(1L, changedCamp); // then - final ChessGame chessGame = chessGameService.getChessGame(1L); + final ChessGame chessGame = chessGameService.getOrCreateChessGame(1L); final CampType campType = chessGame.getCurrentCamp(); assertThat(campType) .isEqualTo(changedCamp); @@ -117,7 +117,7 @@ void deletePieces() { chessGameService.deletePieces(source, target); // then - final ChessGame actual = chessGameService.getChessGame(1L); + final ChessGame actual = chessGameService.getOrCreateChessGame(1L); assertThat(actual) .isEqualTo(new ChessGame(ChessBoard.create(Collections.emptyMap()), CampType.WHITE)); } @@ -133,7 +133,7 @@ void clear() { chessGameService.clear(userId); // then - final ChessGame chessGame = chessGameService.getChessGame(userId); + final ChessGame chessGame = chessGameService.getOrCreateChessGame(userId); final ChessGame expected = new ChessGame(CampType.WHITE); assertThat(chessGame) .isEqualTo(expected); diff --git a/src/test/java/chess/service/UserServiceTestHandler.java b/src/test/java/chess/service/UserServiceTestHandler.java index 4acb520774a..e7bac537823 100644 --- a/src/test/java/chess/service/UserServiceTestHandler.java +++ b/src/test/java/chess/service/UserServiceTestHandler.java @@ -10,12 +10,12 @@ class UserServiceTestHandler { @Test @DisplayName("사용자의 이름이 이미 저장되어 있다면, 존재하는 사용자의 아이디를 반환한다.") - void getUserId_exist() { + void getOrCreateUserId_exist() { // given final UserService userService = new UserService(new MockUserDao()); // when - Long userId = userService.getUserId("journey"); + Long userId = userService.getOrCreateUserId("journey"); // then assertThat(userId) @@ -24,12 +24,12 @@ void getUserId_exist() { @Test @DisplayName("사용자의 이름이 저장되지 않았다면, 새롭게 저장 후 저장된 아이디를 반환한다.") - void getUserId_new() { + void getOrCreateUserId_new() { // given final UserService userService = new UserService(new MockUserDao()); // when - Long userId = userService.getUserId("hello"); + Long userId = userService.getOrCreateUserId("hello"); // then assertThat(userId) From 69d4c586e92d0d82dfdc77783514c8ca351400d3 Mon Sep 17 00:00:00 2001 From: jiwon Date: Thu, 30 Mar 2023 21:04:32 +0900 Subject: [PATCH 70/76] =?UTF-8?q?test:=20assertAll=EB=A1=9C=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=84=B0=EB=A7=81=EC=9D=84=20=EC=A7=84=ED=96=89?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chess/domain/board/ChessBoardTest.java | 14 ++++----- .../java/chess/domain/chess/CampTypeTest.java | 8 ++--- .../java/chess/domain/piece/MoveTest.java | 8 ++--- .../java/chess/domain/piece/PieceTest.java | 29 ++++++------------- 4 files changed, 20 insertions(+), 39 deletions(-) diff --git a/src/test/java/chess/domain/board/ChessBoardTest.java b/src/test/java/chess/domain/board/ChessBoardTest.java index 564260ae040..39978450e40 100644 --- a/src/test/java/chess/domain/board/ChessBoardTest.java +++ b/src/test/java/chess/domain/board/ChessBoardTest.java @@ -17,6 +17,7 @@ import java.util.Map; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; class ChessBoardTest { @@ -118,11 +119,8 @@ void getAliveKings() { new Piece(PieceType.KING, CampType.BLACK, new King())); // then - assertThat(aliveKings) - .isEqualTo(expected); - - assertThat(aliveKings.size()) - .isSameAs(2); + assertAll(() -> assertThat(aliveKings).isEqualTo(expected), + () -> assertThat(aliveKings.size()).isSameAs(2)); } @Test @@ -136,9 +134,7 @@ void getBoardByCamp() { final Map blackBoard = chessBoard.getBoardByCamp(CampType.BLACK); // then - assertThat(whiteBoard.size()) - .isEqualTo(16); - assertThat(blackBoard.size()) - .isEqualTo(16); + assertAll(() -> assertThat(whiteBoard.size()).isEqualTo(16), + () -> assertThat(blackBoard.size()).isEqualTo(16)); } } diff --git a/src/test/java/chess/domain/chess/CampTypeTest.java b/src/test/java/chess/domain/chess/CampTypeTest.java index 1290f49c7d5..90b9d26483d 100644 --- a/src/test/java/chess/domain/chess/CampTypeTest.java +++ b/src/test/java/chess/domain/chess/CampTypeTest.java @@ -6,6 +6,7 @@ import org.junit.jupiter.params.provider.CsvSource; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; class CampTypeTest { @@ -32,10 +33,7 @@ void changeTurn() { CampType blackActual = black.changeTurn(); // then - assertThat(whiteActual) - .isEqualTo(black); - - assertThat(blackActual) - .isEqualTo(white); + assertAll(() -> assertThat(whiteActual).isEqualTo(black), + () -> assertThat(blackActual).isEqualTo(white)); } } diff --git a/src/test/java/chess/domain/piece/MoveTest.java b/src/test/java/chess/domain/piece/MoveTest.java index 5481effe551..d2b30c07dc7 100644 --- a/src/test/java/chess/domain/piece/MoveTest.java +++ b/src/test/java/chess/domain/piece/MoveTest.java @@ -18,6 +18,7 @@ import static chess.domain.piece.move.Direction.UP_LEFT; import static chess.domain.piece.move.Direction.UP_RIGHT; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; public class MoveTest { @@ -105,10 +106,7 @@ void pawn_getAllPositions() { final Location blackActual = Move.getLocation(source, blackDirections, moveCount); // then - assertThat(whiteExpected) - .isEqualTo(whiteActual); - - assertThat(blackExpected) - .isEqualTo(blackActual); + assertAll(() -> assertThat(whiteExpected).isEqualTo(whiteActual), + () -> assertThat(blackExpected).isEqualTo(blackActual)); } } diff --git a/src/test/java/chess/domain/piece/PieceTest.java b/src/test/java/chess/domain/piece/PieceTest.java index 9147d35ea20..c77a26c8409 100644 --- a/src/test/java/chess/domain/piece/PieceTest.java +++ b/src/test/java/chess/domain/piece/PieceTest.java @@ -9,6 +9,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; class PieceTest { @@ -25,11 +26,8 @@ void isSameCamp_withPiece() { final boolean actualTrue = pawn.isSameCamp(queen); // then - assertThat(actualFalse) - .isFalse(); - - assertThat(actualTrue) - .isTrue(); + assertAll(() -> assertThat(actualFalse).isFalse(), + () -> assertThat(actualTrue).isTrue()); } @Test @@ -43,11 +41,8 @@ void isSameCamp_withCampType() { boolean actualFalse = pawn.isSameCamp(CampType.BLACK); // then - assertThat(actualTrue) - .isTrue(); - - assertThat(actualFalse) - .isFalse(); + assertAll(() -> assertThat(actualTrue).isTrue(), + () -> assertThat(actualFalse).isFalse()); } @ParameterizedTest(name = "폰은 처음에 기물이 없는 곳으로 최대 2칸 이동할 수 있다.") @@ -148,11 +143,8 @@ void isKing() { final Piece pawn = new Piece(PieceType.PAWN, CampType.WHITE, new Pawn()); // when, then - assertThat(king.isKing()) - .isTrue(); - - assertThat(pawn.isKing()) - .isFalse(); + assertAll(() -> assertThat(king.isKing()).isTrue(), + () -> assertThat(pawn.isKing()).isFalse()); } @Test @@ -163,10 +155,7 @@ void isPawn() { final Piece pawn = new Piece(PieceType.PAWN, CampType.WHITE, new Pawn()); // when, then - assertThat(pawn.isPawn()) - .isTrue(); - - assertThat(king.isPawn()) - .isFalse(); + assertAll(() -> assertThat(pawn.isPawn()).isTrue(), + () -> assertThat(king.isPawn()).isFalse()); } } From a44da589a13d308ef8f4c0b14eb1243a746bae9c Mon Sep 17 00:00:00 2001 From: jiwon Date: Thu, 30 Mar 2023 21:06:47 +0900 Subject: [PATCH 71/76] =?UTF-8?q?feat:=20@BeforeAll=EC=9D=84=20@BeforeEach?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/chess/controller/status/MoveControllerTest.java | 6 ++---- .../java/chess/controller/status/StartControllerTest.java | 6 ++---- .../java/chess/controller/status/StatusControllerTest.java | 6 ++---- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/test/java/chess/controller/status/MoveControllerTest.java b/src/test/java/chess/controller/status/MoveControllerTest.java index c32643a6ca6..15b3fdc06b6 100644 --- a/src/test/java/chess/controller/status/MoveControllerTest.java +++ b/src/test/java/chess/controller/status/MoveControllerTest.java @@ -5,10 +5,9 @@ import chess.service.ChessGameService; import chess.service.MockServiceManagerHandler; import chess.service.ServiceHandler; -import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -18,12 +17,11 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -@TestInstance(TestInstance.Lifecycle.PER_CLASS) class MoveControllerTest { private ChessGameService chessGameService; - @BeforeAll + @BeforeEach void init() { final ServiceHandler mockServiceManagerHandler = new MockServiceManagerHandler(); chessGameService = mockServiceManagerHandler.chessGameService(); diff --git a/src/test/java/chess/controller/status/StartControllerTest.java b/src/test/java/chess/controller/status/StartControllerTest.java index 2f2850d93a6..d2600bee3f1 100644 --- a/src/test/java/chess/controller/status/StartControllerTest.java +++ b/src/test/java/chess/controller/status/StartControllerTest.java @@ -5,22 +5,20 @@ import chess.service.ChessGameService; import chess.service.MockServiceManagerHandler; import chess.service.ServiceHandler; -import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -@TestInstance(TestInstance.Lifecycle.PER_CLASS) class StartControllerTest { private ChessGameService chessGameService; - @BeforeAll + @BeforeEach void init() { final ServiceHandler mockServiceManagerHandler = new MockServiceManagerHandler(); chessGameService = mockServiceManagerHandler.chessGameService(); diff --git a/src/test/java/chess/controller/status/StatusControllerTest.java b/src/test/java/chess/controller/status/StatusControllerTest.java index 8faa747f9d9..b4359ca4440 100644 --- a/src/test/java/chess/controller/status/StatusControllerTest.java +++ b/src/test/java/chess/controller/status/StatusControllerTest.java @@ -5,21 +5,19 @@ import chess.service.ChessGameService; import chess.service.MockServiceManagerHandler; import chess.service.ServiceHandler; -import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInstance; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class StatusControllerTest { private ChessGameService chessGameService; - @BeforeAll + @BeforeEach void init() { final ServiceHandler mockServiceManagerHandler = new MockServiceManagerHandler(); chessGameService = mockServiceManagerHandler.chessGameService(); From e58e2707f8f4b8cd90db0ac513beeff856ae3e1e Mon Sep 17 00:00:00 2001 From: jiwon Date: Thu, 30 Mar 2023 21:34:03 +0900 Subject: [PATCH 72/76] =?UTF-8?q?feat:=20entity=EC=9D=98=20equals,=20hashc?= =?UTF-8?q?ode=EB=A5=BC=20=EC=A0=9C=EA=B1=B0=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - entity의 경우 id를 바탕으로 동등성 체크가 가능하기 때문에 제거한다. --- .../java/chess/dao/chess/PieceDaoImpl.java | 3 +- .../java/chess/entity/ChessGameEntity.java | 17 +---------- src/main/java/chess/entity/PieceEntity.java | 27 +++++------------ src/main/java/chess/entity/UserEntity.java | 15 ---------- .../java/chess/service/ChessBoardService.java | 3 +- .../service/mapper/ChessBoardMapper.java | 5 ++-- .../chess/dao/chess/ChessGameDaoImplTest.java | 11 +++---- .../java/chess/dao/chess/MockPieceDao.java | 4 ++- .../chess/dao/chess/PieceDaoImplTest.java | 16 ++++++++-- .../chess/dao/chess/PieceEntityHelper.java | 29 ++++++++++--------- .../java/chess/dao/user/UserDaoImplTest.java | 4 +-- 11 files changed, 54 insertions(+), 80 deletions(-) diff --git a/src/main/java/chess/dao/chess/PieceDaoImpl.java b/src/main/java/chess/dao/chess/PieceDaoImpl.java index ba1a7317361..0281f7cf28f 100644 --- a/src/main/java/chess/dao/chess/PieceDaoImpl.java +++ b/src/main/java/chess/dao/chess/PieceDaoImpl.java @@ -16,8 +16,9 @@ public PieceDaoImpl(final JdbcTemplate jdbcTemplate) { @Override public List findByChessGameId(final Long chessGameId) { final String query = "SELECT * FROM piece WHERE chess_game_id = ?"; - return jdbcTemplate.findAll(query, (resultSet -> PieceEntity.createWithId( + return jdbcTemplate.findAll(query, (resultSet -> PieceEntity.create( resultSet.getLong("piece_id"), + resultSet.getLong("chess_game_id"), resultSet.getInt("piece_rank"), resultSet.getInt("piece_file"), resultSet.getString("piece_type"), diff --git a/src/main/java/chess/entity/ChessGameEntity.java b/src/main/java/chess/entity/ChessGameEntity.java index 00bd7628182..4b4390bb7ff 100644 --- a/src/main/java/chess/entity/ChessGameEntity.java +++ b/src/main/java/chess/entity/ChessGameEntity.java @@ -1,7 +1,5 @@ package chess.entity; -import java.util.Objects; - public final class ChessGameEntity { private Long id; private final String currentCamp; @@ -17,20 +15,7 @@ public ChessGameEntity(final String currentCamp, final Long userId) { this.currentCamp = currentCamp; this.userId = userId; } - - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - final ChessGameEntity that = (ChessGameEntity) o; - return Objects.equals(id, that.id) && Objects.equals(currentCamp, that.currentCamp) && Objects.equals(userId, that.userId); - } - - @Override - public int hashCode() { - return Objects.hash(id, currentCamp, userId); - } - + public Long getId() { return id; } diff --git a/src/main/java/chess/entity/PieceEntity.java b/src/main/java/chess/entity/PieceEntity.java index 78b76556036..fae4a9e0bcc 100644 --- a/src/main/java/chess/entity/PieceEntity.java +++ b/src/main/java/chess/entity/PieceEntity.java @@ -1,10 +1,8 @@ package chess.entity; -import java.util.Objects; - public final class PieceEntity { private Long id; - private Long chessGameId; + private final Long chessGameId; private final Integer rank; private final Integer file; private String pieceType; @@ -26,9 +24,9 @@ public PieceEntity(final Long chessGameId, final Integer rank, final Integer fil this.file = file; } - public static PieceEntity createWithId(final Long id, final Integer rank, final Integer file, - final String pieceType, final String campType) { - return new PieceEntity(id, null, rank, file, pieceType, campType); + public static PieceEntity create(final Long id, final Long chessGameId, final Integer rank, + final Integer file, final String pieceType, final String campType) { + return new PieceEntity(id, chessGameId, rank, file, pieceType, campType); } public static PieceEntity createWithChessGameId(final Long chessGameId, final Integer rank, final Integer file, @@ -40,19 +38,6 @@ public static PieceEntity createWithLocation(final Long chessGameId, final Integ return new PieceEntity(chessGameId, rank, file); } - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - final PieceEntity that = (PieceEntity) o; - return Objects.equals(id, that.id) && Objects.equals(rank, that.rank) && Objects.equals(file, that.file) && Objects.equals(pieceType, that.pieceType) && Objects.equals(campType, that.campType); - } - - @Override - public int hashCode() { - return Objects.hash(id, rank, file, pieceType, campType); - } - @Override public String toString() { return "PieceEntity{" + @@ -65,6 +50,10 @@ public String toString() { '}'; } + public Long getId() { + return id; + } + public Integer getRank() { return rank; } diff --git a/src/main/java/chess/entity/UserEntity.java b/src/main/java/chess/entity/UserEntity.java index d0bf9ca8243..4a90d440ac2 100644 --- a/src/main/java/chess/entity/UserEntity.java +++ b/src/main/java/chess/entity/UserEntity.java @@ -1,7 +1,5 @@ package chess.entity; -import java.util.Objects; - public final class UserEntity { private Long id; private final String name; @@ -15,19 +13,6 @@ public UserEntity(final String name) { this.name = name; } - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - final UserEntity that = (UserEntity) o; - return Objects.equals(id, that.id) && Objects.equals(name, that.name); - } - - @Override - public int hashCode() { - return Objects.hash(id, name); - } - public Long getId() { return id; } diff --git a/src/main/java/chess/service/ChessBoardService.java b/src/main/java/chess/service/ChessBoardService.java index 4cdf1ee0f86..bd91ec821b9 100644 --- a/src/main/java/chess/service/ChessBoardService.java +++ b/src/main/java/chess/service/ChessBoardService.java @@ -19,8 +19,7 @@ public class ChessBoardService { ChessBoard getByChessGameId(final Long chessGameId) { final List pieceEntities = pieceDao.findByChessGameId(chessGameId); - final Map board = ChessBoardMapper.from(pieceEntities); - return ChessBoard.create(board); + return ChessBoardMapper.from(pieceEntities); } void savePiece(final PieceEntity pieceEntity) { diff --git a/src/main/java/chess/service/mapper/ChessBoardMapper.java b/src/main/java/chess/service/mapper/ChessBoardMapper.java index 8fa586d5810..f0a20319ed2 100644 --- a/src/main/java/chess/service/mapper/ChessBoardMapper.java +++ b/src/main/java/chess/service/mapper/ChessBoardMapper.java @@ -1,5 +1,6 @@ package chess.service.mapper; +import chess.domain.board.ChessBoard; import chess.domain.chess.CampType; import chess.domain.piece.Movable; import chess.domain.piece.Piece; @@ -13,7 +14,7 @@ public final class ChessBoardMapper { - public static Map from(final List pieceEntities) { + public static ChessBoard from(final List pieceEntities) { final Map chessBoard = new HashMap<>(); for (PieceEntity pieceEntity : pieceEntities) { final Position position = new Position(pieceEntity.getRank(), pieceEntity.getFile()); @@ -22,6 +23,6 @@ public static Map from(final List pieceEntities) { final Movable movable = MovableMapper.from(pieceType); chessBoard.put(position, new Piece(pieceType, campType, movable)); } - return chessBoard; + return ChessBoard.create(chessBoard); } } diff --git a/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java b/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java index 1f8e3bb8ca7..d2913398ecd 100644 --- a/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java +++ b/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java @@ -16,13 +16,14 @@ class ChessGameDaoImplTest { void findByUserId() { // given final ChessGameDao chessGameDao = new MockChessGameDao(); - final ChessGameEntity expected = new ChessGameEntity(1L, "WHITE", 1L); - chessGameDao.save(expected); + final ChessGameEntity createdChessGameEntity = new ChessGameEntity(1L, "WHITE", 1L); + chessGameDao.save(createdChessGameEntity); + final Long expected = createdChessGameEntity.getId(); final long userId = 1L; // when final Optional chessGameEntity = chessGameDao.findByUserId(userId); - final ChessGameEntity actual = chessGameEntity.get(); + final Long actual = chessGameEntity.orElseThrow().getId(); // then assertThat(actual) @@ -64,13 +65,13 @@ void updateCurrentCampById() { // given final ChessGameDao chessGameDao = new MockChessGameDao(); final Long savedChessGameId = chessGameDao.save(new ChessGameEntity("WHITE", 1L)); - final Optional expected = Optional.of(new ChessGameEntity("BLACK", 1L)); + final Long expected = new ChessGameEntity("BLACK", 1L).getId(); // when chessGameDao.updateCurrentCampById(savedChessGameId, CampType.BLACK); // then - final Optional actual = chessGameDao.findByUserId(1L); + final Long actual = chessGameDao.findByUserId(1L).orElseThrow().getId(); assertThat(actual) .isEqualTo(expected); } diff --git a/src/test/java/chess/dao/chess/MockPieceDao.java b/src/test/java/chess/dao/chess/MockPieceDao.java index 541b62c4c5c..942f023e6b2 100644 --- a/src/test/java/chess/dao/chess/MockPieceDao.java +++ b/src/test/java/chess/dao/chess/MockPieceDao.java @@ -17,7 +17,9 @@ public class MockPieceDao implements PieceDao { public List findByChessGameId(final Long chessGameId) { return STORAGE.values().stream() .filter(pieceEntity -> pieceEntity.getChessGameId().equals(chessGameId)) - .map(pieceEntity -> PieceEntity.createWithChessGameId(pieceEntity.getChessGameId(), pieceEntity.getRank(), + .map(pieceEntity -> PieceEntity.create( + pieceEntity.getId(), + pieceEntity.getChessGameId(), pieceEntity.getRank(), pieceEntity.getFile(), pieceEntity.getPieceType(), pieceEntity.getCampType())) .collect(Collectors.toUnmodifiableList()); } diff --git a/src/test/java/chess/dao/chess/PieceDaoImplTest.java b/src/test/java/chess/dao/chess/PieceDaoImplTest.java index b1f1fd200d9..480e3326e3d 100644 --- a/src/test/java/chess/dao/chess/PieceDaoImplTest.java +++ b/src/test/java/chess/dao/chess/PieceDaoImplTest.java @@ -6,6 +6,7 @@ import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -23,10 +24,13 @@ void findByChessGameId() { final List findChessEntities = pieceDao.findByChessGameId(chessGameId); // then - assertThat(findChessEntities) - .isEqualTo(PieceEntityHelper.createPieceEntities(chessGameId)); + final List actual = getPieceEntityIds(findChessEntities); + final List expected = getPieceEntityIds(pieceEntities); - assertThat(findChessEntities.size()) + assertThat(actual) + .isEqualTo(expected); + + assertThat(actual.size()) .isSameAs(18); } @@ -82,4 +86,10 @@ void deleteByChessGameId() { assertThat(pieceDao.findByChessGameId(1L)) .isEqualTo(Collections.emptyList()); } + + private List getPieceEntityIds(final List pieceEntities) { + return pieceEntities.stream() + .map(PieceEntity::getId) + .collect(Collectors.toUnmodifiableList()); + } } diff --git a/src/test/java/chess/dao/chess/PieceEntityHelper.java b/src/test/java/chess/dao/chess/PieceEntityHelper.java index b86b849ac74..b4a4033433d 100644 --- a/src/test/java/chess/dao/chess/PieceEntityHelper.java +++ b/src/test/java/chess/dao/chess/PieceEntityHelper.java @@ -9,28 +9,29 @@ public class PieceEntityHelper { public static List createPieceEntities(final Long chessGameId) { final List results = new ArrayList<>(); - results.addAll(createMockPieces(chessGameId, 0, "WHITE")); - results.addAll(createMockPawnPieces(chessGameId, 1, "WHITE")); - results.addAll(createMockPawnPieces(chessGameId, 6, "BLACK")); - results.addAll(createMockPieces(chessGameId, 7, "BLACK")); + results.addAll(createMockPieces(1L, chessGameId, 0, "WHITE")); + results.addAll(createMockPawnPieces(6L, chessGameId, 1, "WHITE")); + results.addAll(createMockPawnPieces(10L, chessGameId, 6, "BLACK")); + results.addAll(createMockPieces(14L, chessGameId, 7, "BLACK")); return results; } - private static List createMockPieces(final long chessGameId, final int rank, - final String campType) { + private static List createMockPieces(final long id, final long chessGameId, + final int rank, final String campType) { final List results = new ArrayList<>(); - results.add(PieceEntity.createWithChessGameId(chessGameId, rank, 0, "ROOK", campType)); - results.add(PieceEntity.createWithChessGameId(chessGameId, rank, 1, "KNIGHT", campType)); - results.add(PieceEntity.createWithChessGameId(chessGameId, rank, 2, "BISHOP", campType)); - results.add(PieceEntity.createWithChessGameId(chessGameId, rank, 3, "QUEEN", campType)); - results.add(PieceEntity.createWithChessGameId(chessGameId, rank, 4, "KING", campType)); + results.add(PieceEntity.create(id, chessGameId, rank, 0, "ROOK", campType)); + results.add(PieceEntity.create(id + 1, chessGameId, rank, 1, "KNIGHT", campType)); + results.add(PieceEntity.create(id + 2, chessGameId, rank, 2, "BISHOP", campType)); + results.add(PieceEntity.create(id + 3, chessGameId, rank, 3, "QUEEN", campType)); + results.add(PieceEntity.create(id + 4, chessGameId, rank, 4, "KING", campType)); return results; } - private static List createMockPawnPieces(final long chessGameId, final int rank, final String campType) { + private static List createMockPawnPieces(final long id, final long chessGameId, + final int rank, final String campType) { final List results = new ArrayList<>(); - for (int file = 0; file < 4; file++) { - results.add(PieceEntity.createWithChessGameId(chessGameId, rank, file, "PAWN", campType)); + for (int index = 0; index < 4; index++) { + results.add(PieceEntity.create(id + index, chessGameId, rank, index, "PAWN", campType)); } return results; } diff --git a/src/test/java/chess/dao/user/UserDaoImplTest.java b/src/test/java/chess/dao/user/UserDaoImplTest.java index 72db22e6ab9..3c1bb5f2481 100644 --- a/src/test/java/chess/dao/user/UserDaoImplTest.java +++ b/src/test/java/chess/dao/user/UserDaoImplTest.java @@ -17,11 +17,11 @@ void findByName() { final UserDao userDao = new MockUserDao(); final String name = "journey"; userDao.save(name); - final UserEntity expected = new UserEntity(1L, name); + final Long expected = new UserEntity(1L, name).getId(); // when final Optional userEntity = userDao.findByName(name); - final UserEntity actual = userEntity.get(); + final Long actual = userEntity.orElseThrow().getId(); // then assertThat(actual) From c2a1f45922defc22ba27a073635ecc7ecffc2de6 Mon Sep 17 00:00:00 2001 From: jiwon Date: Thu, 30 Mar 2023 21:59:21 +0900 Subject: [PATCH 73/76] =?UTF-8?q?refactor:=20long=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20wrapper=20?= =?UTF-8?q?=ED=98=95=EC=9D=84=20=EC=A0=9C=EA=B1=B0=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/chess/controller/ChessHandler.java | 6 ++--- .../controller/status/MoveController.java | 10 ++++----- .../controller/status/StartController.java | 4 ++-- .../controller/status/StatusController.java | 4 ++-- .../java/chess/dao/chess/ChessGameDao.java | 6 ++--- .../chess/dao/chess/ChessGameDaoImpl.java | 6 ++--- src/main/java/chess/dao/chess/PieceDao.java | 6 ++--- .../java/chess/dao/chess/PieceDaoImpl.java | 10 ++++----- .../java/chess/service/ChessBoardService.java | 2 +- .../java/chess/service/ChessGameService.java | 16 +++++++------- .../chess/dao/chess/ChessGameDaoImplTest.java | 12 +++++----- .../chess/dao/chess/MockChessGameDao.java | 10 ++++----- .../java/chess/dao/chess/MockPieceDao.java | 6 ++--- .../java/chess/dao/user/UserDaoImplTest.java | 4 ++-- .../service/ChessGameServiceTestHandler.java | 22 +++++++++---------- 15 files changed, 62 insertions(+), 62 deletions(-) diff --git a/src/main/java/chess/controller/ChessHandler.java b/src/main/java/chess/controller/ChessHandler.java index 817ad481844..f1b4d1a2d52 100644 --- a/src/main/java/chess/controller/ChessHandler.java +++ b/src/main/java/chess/controller/ChessHandler.java @@ -25,7 +25,7 @@ public ChessHandler(final ServiceManager serviceManager) { } public void run() { - final Long userId = getUserId(); + final long userId = getUserId(); OutputView.printStartMessage(); Controller controller = new StartController(userId, chessGameService); while (controller.isRun()) { @@ -48,12 +48,12 @@ private Controller play(Controller controller) { } } - private Long getUserId() { + private long getUserId() { OutputView.printUserNameInputMessage(); return getUserIdWithRetry(InputView::getCommand); } - private Long getUserIdWithRetry(final Supplier supplier) { + private long getUserIdWithRetry(final Supplier supplier) { try { final String name = supplier.get(); return userService.getOrCreateUserId(name); diff --git a/src/main/java/chess/controller/status/MoveController.java b/src/main/java/chess/controller/status/MoveController.java index 800763ecd5f..3cd714e7a59 100644 --- a/src/main/java/chess/controller/status/MoveController.java +++ b/src/main/java/chess/controller/status/MoveController.java @@ -14,10 +14,10 @@ public final class MoveController implements Controller { - private final Long userId; + private final long userId; private final ChessGameService chessGameService; - MoveController(final Long userId, final ChessGameService chessGameService) { + MoveController(final long userId, final ChessGameService chessGameService) { this.userId = userId; this.chessGameService = chessGameService; } @@ -72,19 +72,19 @@ private void play(final List commands, final ChessGame chessGame) { } private void savePlayInfo(final Position source, final Position target, final ChessGame chessGame) { - final Long chessGameId = chessGameService.getChessGameId(userId); + final long chessGameId = chessGameService.getChessGameId(userId); deletePieces(source, target, chessGameId); savePieces(target, chessGameId, chessGame); chessGameService.updateCurrentCamp(chessGameId, chessGame.getCurrentCamp()); } - private void deletePieces(final Position source, final Position target, final Long chessGameId) { + private void deletePieces(final Position source, final Position target, final long chessGameId) { final PieceEntity sourcePiece = PieceEntity.createWithLocation(chessGameId, source.getRank(), source.getFile()); final PieceEntity targetPiece = PieceEntity.createWithLocation(chessGameId, target.getRank(), target.getFile()); chessGameService.deletePieces(sourcePiece, targetPiece); } - private void savePieces(final Position target, final Long chessGameId, final ChessGame chessGame) { + private void savePieces(final Position target, final long chessGameId, final ChessGame chessGame) { final Map chessBoard = chessGame.getChessBoard(); final Piece piece = chessBoard.get(target); final PieceEntity savedPiece = PieceEntity.createWithChessGameId(chessGameId, target.getRank(), diff --git a/src/main/java/chess/controller/status/StartController.java b/src/main/java/chess/controller/status/StartController.java index 9e15ea8e7b0..924aea513d5 100644 --- a/src/main/java/chess/controller/status/StartController.java +++ b/src/main/java/chess/controller/status/StartController.java @@ -7,10 +7,10 @@ import java.util.Optional; public final class StartController implements Controller { - private final Long userId; + private final long userId; private final ChessGameService chessGameService; - public StartController(final Long userId, final ChessGameService chessGameService) { + public StartController(final long userId, final ChessGameService chessGameService) { this.userId = userId; this.chessGameService = chessGameService; } diff --git a/src/main/java/chess/controller/status/StatusController.java b/src/main/java/chess/controller/status/StatusController.java index 68c413ab74a..1a5b98b3f3a 100644 --- a/src/main/java/chess/controller/status/StatusController.java +++ b/src/main/java/chess/controller/status/StatusController.java @@ -12,10 +12,10 @@ import java.util.Optional; public final class StatusController implements Controller { - private final Long userId; + private final long userId; private final ChessGameService chessGameService; - StatusController(final Long userId, final ChessGameService chessGameService) { + StatusController(final long userId, final ChessGameService chessGameService) { this.userId = userId; this.chessGameService = chessGameService; } diff --git a/src/main/java/chess/dao/chess/ChessGameDao.java b/src/main/java/chess/dao/chess/ChessGameDao.java index dcc7881d763..6c5f2e50a6e 100644 --- a/src/main/java/chess/dao/chess/ChessGameDao.java +++ b/src/main/java/chess/dao/chess/ChessGameDao.java @@ -6,11 +6,11 @@ import java.util.Optional; public interface ChessGameDao { - Optional findByUserId(final Long userId); + Optional findByUserId(final long userId); Long save(final ChessGameEntity chessGameEntity); - void updateCurrentCampById(Long id, CampType currentCamp); + void updateCurrentCampById(long id, CampType currentCamp); - void deleteByUserId(Long userId); + void deleteByUserId(long userId); } diff --git a/src/main/java/chess/dao/chess/ChessGameDaoImpl.java b/src/main/java/chess/dao/chess/ChessGameDaoImpl.java index dbb756fb506..6fd67ccfec0 100644 --- a/src/main/java/chess/dao/chess/ChessGameDaoImpl.java +++ b/src/main/java/chess/dao/chess/ChessGameDaoImpl.java @@ -14,7 +14,7 @@ public ChessGameDaoImpl(final JdbcTemplate jdbcTemplate) { } @Override - public Optional findByUserId(final Long userId) { + public Optional findByUserId(final long userId) { final String query = "SELECT * FROM chess_game WHERE user_id = ?"; return jdbcTemplate.findOne(query, (resultSet -> new ChessGameEntity( @@ -34,7 +34,7 @@ public Long save(final ChessGameEntity chessGameEntity) { } @Override - public void updateCurrentCampById(final Long id, final CampType currentCamp) { + public void updateCurrentCampById(final long id, final CampType currentCamp) { final String query = "UPDATE chess_game SET current_camp = ? WHERE chess_game_id = ?"; jdbcTemplate.executeUpdate(query, @@ -43,7 +43,7 @@ public void updateCurrentCampById(final Long id, final CampType currentCamp) { } @Override - public void deleteByUserId(final Long userId) { + public void deleteByUserId(final long userId) { final String query = "DELETE FROM chess_game where user_id = ?"; jdbcTemplate.executeUpdate(query, diff --git a/src/main/java/chess/dao/chess/PieceDao.java b/src/main/java/chess/dao/chess/PieceDao.java index 45b1ec12533..d3df695ac8d 100644 --- a/src/main/java/chess/dao/chess/PieceDao.java +++ b/src/main/java/chess/dao/chess/PieceDao.java @@ -5,11 +5,11 @@ import java.util.List; public interface PieceDao { - List findByChessGameId(final Long chessGameId); + List findByChessGameId(final long chessGameId); Long save(final PieceEntity pieceEntity); - void deleteByPositions(final Long chessGameId, final PieceEntity... pieceEntity); + void deleteByPositions(final long chessGameId, final PieceEntity... pieceEntity); - void deleteByChessGameId(Long chessGameId); + void deleteByChessGameId(long chessGameId); } diff --git a/src/main/java/chess/dao/chess/PieceDaoImpl.java b/src/main/java/chess/dao/chess/PieceDaoImpl.java index 0281f7cf28f..1b6280d2b3f 100644 --- a/src/main/java/chess/dao/chess/PieceDaoImpl.java +++ b/src/main/java/chess/dao/chess/PieceDaoImpl.java @@ -14,7 +14,7 @@ public PieceDaoImpl(final JdbcTemplate jdbcTemplate) { } @Override - public List findByChessGameId(final Long chessGameId) { + public List findByChessGameId(final long chessGameId) { final String query = "SELECT * FROM piece WHERE chess_game_id = ?"; return jdbcTemplate.findAll(query, (resultSet -> PieceEntity.create( resultSet.getLong("piece_id"), @@ -37,7 +37,7 @@ public Long save(final PieceEntity pieceEntity) { } @Override - public void deleteByPositions(final Long chessGameId, final PieceEntity... pieceEntity) { + public void deleteByPositions(final long chessGameId, final PieceEntity... pieceEntity) { if (pieceEntity.length == 1) { deleteOneByPosition(chessGameId, pieceEntity[0]); } @@ -47,14 +47,14 @@ public void deleteByPositions(final Long chessGameId, final PieceEntity... piece } @Override - public void deleteByChessGameId(final Long chessGameId) { + public void deleteByChessGameId(final long chessGameId) { final String query = "DELETE FROM piece where chess_game_id = ?"; jdbcTemplate.executeUpdate(query, String.valueOf(chessGameId)); } - private void deleteOneByPosition(final Long chessGameId, final PieceEntity pieceEntity) { + private void deleteOneByPosition(final long chessGameId, final PieceEntity pieceEntity) { final String query = "DELETE FROM piece WHERE chess_game_id = ? " + "and piece_rank = ? and piece_file = ?"; @@ -64,7 +64,7 @@ private void deleteOneByPosition(final Long chessGameId, final PieceEntity piece String.valueOf(pieceEntity.getFile())); } - private void deleteTwoByPosition(final Long chessGameId, final PieceEntity source, final PieceEntity destination) { + private void deleteTwoByPosition(final long chessGameId, final PieceEntity source, final PieceEntity destination) { final String query = "DELETE FROM piece WHERE chess_game_id = ? " + "and (" + " (piece_rank = ? and piece_file = ?) or (piece_rank = ? and piece_file = ?)" + diff --git a/src/main/java/chess/service/ChessBoardService.java b/src/main/java/chess/service/ChessBoardService.java index bd91ec821b9..0f842efdb7e 100644 --- a/src/main/java/chess/service/ChessBoardService.java +++ b/src/main/java/chess/service/ChessBoardService.java @@ -17,7 +17,7 @@ public class ChessBoardService { this.pieceDao = pieceDao; } - ChessBoard getByChessGameId(final Long chessGameId) { + ChessBoard getByChessGameId(final long chessGameId) { final List pieceEntities = pieceDao.findByChessGameId(chessGameId); return ChessBoardMapper.from(pieceEntities); } diff --git a/src/main/java/chess/service/ChessGameService.java b/src/main/java/chess/service/ChessGameService.java index d6680383869..92cd46c93d9 100644 --- a/src/main/java/chess/service/ChessGameService.java +++ b/src/main/java/chess/service/ChessGameService.java @@ -18,7 +18,7 @@ public ChessGameService(final ChessGameDao chessGameDao, final ChessBoardService this.chessBoardService = chessBoardService; } - public ChessGame getOrCreateChessGame(final Long userId) { + public ChessGame getOrCreateChessGame(final long userId) { final Optional findChessGameEntity = chessGameDao.findByUserId(userId); if (findChessGameEntity.isEmpty()) { return getNewChessGame(userId); @@ -27,7 +27,7 @@ public ChessGame getOrCreateChessGame(final Long userId) { return getExistChessGame(chessGameEntity); } - public Long getChessGameId(final Long userId) { + public long getChessGameId(final long userId) { final Optional findChessGameEntity = chessGameDao.findByUserId(userId); if (findChessGameEntity.isEmpty()) { throw new IllegalArgumentException("저장된 데이터가 존재하지 않습니다."); @@ -39,7 +39,7 @@ public void savePiece(final PieceEntity pieceEntity) { chessBoardService.savePiece(pieceEntity); } - public void updateCurrentCamp(final Long chessGameId, final CampType currentCamp) { + public void updateCurrentCamp(final long chessGameId, final CampType currentCamp) { chessGameDao.updateCurrentCampById(chessGameId, currentCamp); } @@ -47,15 +47,15 @@ public void deletePieces(final PieceEntity sourcePiece, final PieceEntity target chessBoardService.deletePieces(sourcePiece, targetPiece); } - public void clear(final Long userId) { - final Long chessGameId = getChessGameId(userId); + public void clear(final long userId) { + final long chessGameId = getChessGameId(userId); chessBoardService.deleteByChessGameId(chessGameId); chessGameDao.deleteByUserId(userId); } - private ChessGame getNewChessGame(final Long userId) { + private ChessGame getNewChessGame(final long userId) { final CampType currentCamp = CampType.WHITE; - final Long chessGameId = chessGameDao.save(new ChessGameEntity(currentCamp.name(), userId)); + final long chessGameId = chessGameDao.save(new ChessGameEntity(currentCamp.name(), userId)); final ChessGame chessGame = new ChessGame(currentCamp); chessBoardService.saveAll(chessGameId, chessGame.getChessBoard()); return chessGame; @@ -68,7 +68,7 @@ private ChessGame getExistChessGame(final ChessGameEntity chessGameEntity) { } private ChessBoard getChessBoard(final ChessGameEntity chessGameEntity) { - final Long chessGameId = chessGameEntity.getId(); + final long chessGameId = chessGameEntity.getId(); return chessBoardService.getByChessGameId(chessGameId); } } diff --git a/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java b/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java index d2913398ecd..5640368166a 100644 --- a/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java +++ b/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java @@ -18,12 +18,12 @@ void findByUserId() { final ChessGameDao chessGameDao = new MockChessGameDao(); final ChessGameEntity createdChessGameEntity = new ChessGameEntity(1L, "WHITE", 1L); chessGameDao.save(createdChessGameEntity); - final Long expected = createdChessGameEntity.getId(); + final long expected = createdChessGameEntity.getId(); final long userId = 1L; // when final Optional chessGameEntity = chessGameDao.findByUserId(userId); - final Long actual = chessGameEntity.orElseThrow().getId(); + final long actual = chessGameEntity.orElseThrow().getId(); // then assertThat(actual) @@ -52,7 +52,7 @@ void save() { final ChessGameDao chessGameDao = new MockChessGameDao(); // when - final Long savedChessGameId = chessGameDao.save(new ChessGameEntity("WHITE", 1L)); + final long savedChessGameId = chessGameDao.save(new ChessGameEntity("WHITE", 1L)); // then assertThat(savedChessGameId) @@ -64,14 +64,14 @@ void save() { void updateCurrentCampById() { // given final ChessGameDao chessGameDao = new MockChessGameDao(); - final Long savedChessGameId = chessGameDao.save(new ChessGameEntity("WHITE", 1L)); - final Long expected = new ChessGameEntity("BLACK", 1L).getId(); + final long savedChessGameId = chessGameDao.save(new ChessGameEntity("WHITE", 1L)); + final long expected = new ChessGameEntity(1L, "BLACK", 1L).getId(); // when chessGameDao.updateCurrentCampById(savedChessGameId, CampType.BLACK); // then - final Long actual = chessGameDao.findByUserId(1L).orElseThrow().getId(); + final long actual = chessGameDao.findByUserId(1L).orElseThrow().getId(); assertThat(actual) .isEqualTo(expected); } diff --git a/src/test/java/chess/dao/chess/MockChessGameDao.java b/src/test/java/chess/dao/chess/MockChessGameDao.java index 273dbdb0253..00f07c43924 100644 --- a/src/test/java/chess/dao/chess/MockChessGameDao.java +++ b/src/test/java/chess/dao/chess/MockChessGameDao.java @@ -14,7 +14,7 @@ public class MockChessGameDao implements ChessGameDao { private final AtomicLong pk = new AtomicLong(0L); @Override - public Optional findByUserId(final Long userId) { + public Optional findByUserId(final long userId) { return STORAGE.values().stream() .filter(chessGameEntity -> chessGameEntity.getUserId().equals(userId)) .map(chessGameEntity -> new ChessGameEntity(chessGameEntity.getId(), chessGameEntity.getCurrentCamp(), @@ -25,20 +25,20 @@ public Optional findByUserId(final Long userId) { @Override public Long save(final ChessGameEntity chessGameEntity) { final long key = pk.addAndGet(1L); - ChessGameEntity savedChessGameEntity = new ChessGameEntity(key, + final ChessGameEntity savedChessGameEntity = new ChessGameEntity(key, chessGameEntity.getCurrentCamp(), chessGameEntity.getUserId()); STORAGE.put(key, savedChessGameEntity); return pk.longValue(); } @Override - public void updateCurrentCampById(final Long id, final CampType currentCamp) { + public void updateCurrentCampById(final long id, final CampType currentCamp) { final ChessGameEntity chessGameEntity = STORAGE.get(id); - STORAGE.put(id, new ChessGameEntity(currentCamp.name(), chessGameEntity.getUserId())); + STORAGE.put(id, new ChessGameEntity(chessGameEntity.getId(), currentCamp.name(), chessGameEntity.getUserId())); } @Override - public void deleteByUserId(final Long userId) { + public void deleteByUserId(final long userId) { STORAGE.keySet().stream() .filter(key -> Objects.equals(STORAGE.get(key).getUserId(), userId)) .forEach(STORAGE::remove); diff --git a/src/test/java/chess/dao/chess/MockPieceDao.java b/src/test/java/chess/dao/chess/MockPieceDao.java index 942f023e6b2..ef94cbea1ff 100644 --- a/src/test/java/chess/dao/chess/MockPieceDao.java +++ b/src/test/java/chess/dao/chess/MockPieceDao.java @@ -14,7 +14,7 @@ public class MockPieceDao implements PieceDao { private final AtomicLong pk = new AtomicLong(0L); @Override - public List findByChessGameId(final Long chessGameId) { + public List findByChessGameId(final long chessGameId) { return STORAGE.values().stream() .filter(pieceEntity -> pieceEntity.getChessGameId().equals(chessGameId)) .map(pieceEntity -> PieceEntity.create( @@ -31,7 +31,7 @@ public Long save(final PieceEntity pieceEntity) { } @Override - public void deleteByPositions(final Long chessGameId, final PieceEntity... pieceEntity) { + public void deleteByPositions(final long chessGameId, final PieceEntity... pieceEntity) { delete(pieceEntity[0]); if (pieceEntity.length == 2) { delete(pieceEntity[1]); @@ -39,7 +39,7 @@ public void deleteByPositions(final Long chessGameId, final PieceEntity... piece } @Override - public void deleteByChessGameId(final Long chessGameId) { + public void deleteByChessGameId(final long chessGameId) { STORAGE.keySet().stream() .filter(key -> Objects.equals(STORAGE.get(key).getChessGameId(), chessGameId)) .forEach(STORAGE::remove); diff --git a/src/test/java/chess/dao/user/UserDaoImplTest.java b/src/test/java/chess/dao/user/UserDaoImplTest.java index 3c1bb5f2481..911338a317a 100644 --- a/src/test/java/chess/dao/user/UserDaoImplTest.java +++ b/src/test/java/chess/dao/user/UserDaoImplTest.java @@ -17,11 +17,11 @@ void findByName() { final UserDao userDao = new MockUserDao(); final String name = "journey"; userDao.save(name); - final Long expected = new UserEntity(1L, name).getId(); + final long expected = new UserEntity(1L, name).getId(); // when final Optional userEntity = userDao.findByName(name); - final Long actual = userEntity.orElseThrow().getId(); + final long actual = userEntity.orElseThrow().getId(); // then assertThat(actual) diff --git a/src/test/java/chess/service/ChessGameServiceTestHandler.java b/src/test/java/chess/service/ChessGameServiceTestHandler.java index cd3c813a9fc..0719145de47 100644 --- a/src/test/java/chess/service/ChessGameServiceTestHandler.java +++ b/src/test/java/chess/service/ChessGameServiceTestHandler.java @@ -39,7 +39,7 @@ void getOrCreateChessGame_empty() { @DisplayName("사용자의 아이디에 해당하는 체스 게임이 존재하면 해당 게임을 반환한다.") void getOrCreateChessGame() { // given - final Long userId = 1L; + final long userId = 1L; final ChessGameService chessGameService = getChessGameService(userId); final ChessBoard mockProgressBoard = ChessBoardHelper.createMockProgressBoard(); final ChessGame expected = new ChessGame(mockProgressBoard, CampType.WHITE); @@ -56,11 +56,11 @@ void getOrCreateChessGame() { @DisplayName("사용자의 아이디를 기준으로 체스 게임을 조회한다") void getChessGameId() { // given - final Long userId = 1L; + final long userId = 1L; final ChessGameService chessGameService = getChessGameService(userId); // when - Long chessGameId = chessGameService.getChessGameId(userId); + long chessGameId = chessGameService.getChessGameId(userId); // then assertThat(chessGameId) @@ -71,7 +71,7 @@ void getChessGameId() { @DisplayName("체스말 정보를 바탕으로 체스말을 저장한다") void savePiece() { // given - final Long userId = 1L; + final long userId = 1L; final ChessGameService chessGameService = getChessGameService(userId); // when @@ -79,7 +79,7 @@ void savePiece() { "PAWN", "WHITE")); // then - final Long chessGameId = chessGameService.getChessGameId(1L); + final long chessGameId = chessGameService.getChessGameId(1L); assertThat(chessGameId) .isEqualTo(1L); } @@ -88,7 +88,7 @@ void savePiece() { @DisplayName("체스 게임 아이디에 해당하는 진영 정보를 업데이트한다.") void updateCurrentCamp() { // given - final Long userId = 1L; + final long userId = 1L; final ChessGameService chessGameService = getChessGameService(userId); final CampType changedCamp = CampType.BLACK; @@ -106,7 +106,7 @@ void updateCurrentCamp() { @DisplayName("입력받은 위치에 해당하는 체스말을 제거한다") void deletePieces() { // given - final Long userId = 1L; + final long userId = 1L; final MockChessGameDao chessGameDao = new MockChessGameDao(); chessGameDao.save(new ChessGameEntity("WHITE", userId)); final ChessGameService chessGameService = new ChessGameService(chessGameDao, new ChessBoardService(new MockPieceDao())); @@ -126,7 +126,7 @@ void deletePieces() { @DisplayName("사용자의 아이디에 해당하는 체스 기물과 체스판 정보를 제거한다") void clear() { // given - final Long userId = 1L; + final long userId = 1L; final ChessGameService chessGameService = getChessGameService(userId); // when @@ -139,14 +139,14 @@ void clear() { .isEqualTo(expected); } - private ChessGameService getChessGameService(final Long userId) { + private ChessGameService getChessGameService(final long userId) { final MockChessGameDao chessGameDao = new MockChessGameDao(); - Long chessGameId = chessGameDao.save(new ChessGameEntity("WHITE", userId)); + final long chessGameId = chessGameDao.save(new ChessGameEntity(1L, "WHITE", userId)); final MockPieceDao pieceDao = getMockPieceDao(chessGameId); return new ChessGameService(chessGameDao, new ChessBoardService(pieceDao)); } - private MockPieceDao getMockPieceDao(final Long chessGameId) { + private MockPieceDao getMockPieceDao(final long chessGameId) { final List pieceEntities = PieceEntityHelper.createPieceEntities(chessGameId); final MockPieceDao pieceDao = new MockPieceDao(); pieceEntities.forEach(pieceDao::save); From becd15d4896978753bd04ff57ac2d260e688734f Mon Sep 17 00:00:00 2001 From: jiwon Date: Thu, 30 Mar 2023 22:02:33 +0900 Subject: [PATCH 74/76] =?UTF-8?q?refactor:=20save=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=EB=84=A4=EC=9D=B4=EB=B0=8D=EC=9D=84=20insert?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/chess/dao/chess/ChessGameDao.java | 2 +- .../java/chess/dao/chess/ChessGameDaoImpl.java | 2 +- src/main/java/chess/dao/chess/PieceDao.java | 2 +- src/main/java/chess/dao/chess/PieceDaoImpl.java | 2 +- src/main/java/chess/dao/user/UserDao.java | 2 +- src/main/java/chess/dao/user/UserDaoImpl.java | 2 +- src/main/java/chess/service/ChessBoardService.java | 4 ++-- src/main/java/chess/service/ChessGameService.java | 2 +- src/main/java/chess/service/UserService.java | 2 +- .../java/chess/dao/chess/ChessGameDaoImplTest.java | 10 +++++----- .../java/chess/dao/chess/MockChessGameDao.java | 2 +- src/test/java/chess/dao/chess/MockPieceDao.java | 2 +- .../java/chess/dao/chess/PieceDaoImplTest.java | 14 +++++++------- src/test/java/chess/dao/user/MockUserDao.java | 2 +- src/test/java/chess/dao/user/UserDaoImplTest.java | 4 ++-- .../service/ChessBoardServiceTestHandler.java | 2 +- .../chess/service/ChessGameServiceTestHandler.java | 6 +++--- 17 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/main/java/chess/dao/chess/ChessGameDao.java b/src/main/java/chess/dao/chess/ChessGameDao.java index 6c5f2e50a6e..f979a505721 100644 --- a/src/main/java/chess/dao/chess/ChessGameDao.java +++ b/src/main/java/chess/dao/chess/ChessGameDao.java @@ -8,7 +8,7 @@ public interface ChessGameDao { Optional findByUserId(final long userId); - Long save(final ChessGameEntity chessGameEntity); + Long insert(final ChessGameEntity chessGameEntity); void updateCurrentCampById(long id, CampType currentCamp); diff --git a/src/main/java/chess/dao/chess/ChessGameDaoImpl.java b/src/main/java/chess/dao/chess/ChessGameDaoImpl.java index 6fd67ccfec0..686883228e4 100644 --- a/src/main/java/chess/dao/chess/ChessGameDaoImpl.java +++ b/src/main/java/chess/dao/chess/ChessGameDaoImpl.java @@ -25,7 +25,7 @@ public Optional findByUserId(final long userId) { } @Override - public Long save(final ChessGameEntity chessGameEntity) { + public Long insert(final ChessGameEntity chessGameEntity) { final String query = "INSERT INTO chess_game(current_camp, user_id) VALUES (?, ?)"; return jdbcTemplate.executeUpdate(query, diff --git a/src/main/java/chess/dao/chess/PieceDao.java b/src/main/java/chess/dao/chess/PieceDao.java index d3df695ac8d..eb1702d57a8 100644 --- a/src/main/java/chess/dao/chess/PieceDao.java +++ b/src/main/java/chess/dao/chess/PieceDao.java @@ -7,7 +7,7 @@ public interface PieceDao { List findByChessGameId(final long chessGameId); - Long save(final PieceEntity pieceEntity); + Long insert(final PieceEntity pieceEntity); void deleteByPositions(final long chessGameId, final PieceEntity... pieceEntity); diff --git a/src/main/java/chess/dao/chess/PieceDaoImpl.java b/src/main/java/chess/dao/chess/PieceDaoImpl.java index 1b6280d2b3f..88048679901 100644 --- a/src/main/java/chess/dao/chess/PieceDaoImpl.java +++ b/src/main/java/chess/dao/chess/PieceDaoImpl.java @@ -26,7 +26,7 @@ public List findByChessGameId(final long chessGameId) { } @Override - public Long save(final PieceEntity pieceEntity) { + public Long insert(final PieceEntity pieceEntity) { final String query = "INSERT INTO piece(piece_rank, piece_file, piece_type, camp, chess_game_id) " + "VALUES (?, ?, ?, ?, ?)"; return jdbcTemplate.executeUpdate(query, diff --git a/src/main/java/chess/dao/user/UserDao.java b/src/main/java/chess/dao/user/UserDao.java index 7d4e7690cee..baf77003884 100644 --- a/src/main/java/chess/dao/user/UserDao.java +++ b/src/main/java/chess/dao/user/UserDao.java @@ -7,5 +7,5 @@ public interface UserDao { Optional findByName(final String name); - Long save(final String name); + Long insert(final String name); } diff --git a/src/main/java/chess/dao/user/UserDaoImpl.java b/src/main/java/chess/dao/user/UserDaoImpl.java index 3e66c839d05..89a5bb57fb0 100644 --- a/src/main/java/chess/dao/user/UserDaoImpl.java +++ b/src/main/java/chess/dao/user/UserDaoImpl.java @@ -23,7 +23,7 @@ public Optional findByName(final String name) { } @Override - public Long save(final String name) { + public Long insert(final String name) { final String query = "INSERT INTO user(user_name) VALUES(?)"; return jdbcTemplate.executeUpdate(query, name); } diff --git a/src/main/java/chess/service/ChessBoardService.java b/src/main/java/chess/service/ChessBoardService.java index 0f842efdb7e..bb30ddbbc31 100644 --- a/src/main/java/chess/service/ChessBoardService.java +++ b/src/main/java/chess/service/ChessBoardService.java @@ -23,7 +23,7 @@ ChessBoard getByChessGameId(final long chessGameId) { } void savePiece(final PieceEntity pieceEntity) { - pieceDao.save(pieceEntity); + pieceDao.insert(pieceEntity); } void deletePieces(final PieceEntity sourcePiece, final PieceEntity targetPiece) { @@ -36,7 +36,7 @@ void saveAll(final Long chessGameId, final Map chessBoard) { final Piece piece = chessBoard.get(position); PieceEntity pieceEntity = PieceEntity.createWithChessGameId(chessGameId, position.getRank(), position.getFile(), piece.getPieceType().name(), piece.getCampType().name()); - pieceDao.save(pieceEntity); + pieceDao.insert(pieceEntity); } } diff --git a/src/main/java/chess/service/ChessGameService.java b/src/main/java/chess/service/ChessGameService.java index 92cd46c93d9..b11c1fbf58e 100644 --- a/src/main/java/chess/service/ChessGameService.java +++ b/src/main/java/chess/service/ChessGameService.java @@ -55,7 +55,7 @@ public void clear(final long userId) { private ChessGame getNewChessGame(final long userId) { final CampType currentCamp = CampType.WHITE; - final long chessGameId = chessGameDao.save(new ChessGameEntity(currentCamp.name(), userId)); + final long chessGameId = chessGameDao.insert(new ChessGameEntity(currentCamp.name(), userId)); final ChessGame chessGame = new ChessGame(currentCamp); chessBoardService.saveAll(chessGameId, chessGame.getChessBoard()); return chessGame; diff --git a/src/main/java/chess/service/UserService.java b/src/main/java/chess/service/UserService.java index 0092b92bacb..6ca64f9253f 100644 --- a/src/main/java/chess/service/UserService.java +++ b/src/main/java/chess/service/UserService.java @@ -24,6 +24,6 @@ public Long getOrCreateUserId(final String name) { } private Long save(final String name) { - return userDao.save(name); + return userDao.insert(name); } } diff --git a/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java b/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java index 5640368166a..69bee45cc82 100644 --- a/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java +++ b/src/test/java/chess/dao/chess/ChessGameDaoImplTest.java @@ -17,7 +17,7 @@ void findByUserId() { // given final ChessGameDao chessGameDao = new MockChessGameDao(); final ChessGameEntity createdChessGameEntity = new ChessGameEntity(1L, "WHITE", 1L); - chessGameDao.save(createdChessGameEntity); + chessGameDao.insert(createdChessGameEntity); final long expected = createdChessGameEntity.getId(); final long userId = 1L; @@ -47,12 +47,12 @@ void findByUserId_empty() { @Test @DisplayName("사용자가 현재 진행 중인 체스 게임을 저장한다") - void save() { + void insert() { // given final ChessGameDao chessGameDao = new MockChessGameDao(); // when - final long savedChessGameId = chessGameDao.save(new ChessGameEntity("WHITE", 1L)); + final long savedChessGameId = chessGameDao.insert(new ChessGameEntity("WHITE", 1L)); // then assertThat(savedChessGameId) @@ -64,7 +64,7 @@ void save() { void updateCurrentCampById() { // given final ChessGameDao chessGameDao = new MockChessGameDao(); - final long savedChessGameId = chessGameDao.save(new ChessGameEntity("WHITE", 1L)); + final long savedChessGameId = chessGameDao.insert(new ChessGameEntity("WHITE", 1L)); final long expected = new ChessGameEntity(1L, "BLACK", 1L).getId(); // when @@ -81,7 +81,7 @@ void updateCurrentCampById() { void deleteByUserId() { // given final ChessGameDao chessGameDao = new MockChessGameDao(); - chessGameDao.save(new ChessGameEntity("WHITE", 1L)); + chessGameDao.insert(new ChessGameEntity("WHITE", 1L)); // when chessGameDao.deleteByUserId(1L); diff --git a/src/test/java/chess/dao/chess/MockChessGameDao.java b/src/test/java/chess/dao/chess/MockChessGameDao.java index 00f07c43924..505e53e683e 100644 --- a/src/test/java/chess/dao/chess/MockChessGameDao.java +++ b/src/test/java/chess/dao/chess/MockChessGameDao.java @@ -23,7 +23,7 @@ public Optional findByUserId(final long userId) { } @Override - public Long save(final ChessGameEntity chessGameEntity) { + public Long insert(final ChessGameEntity chessGameEntity) { final long key = pk.addAndGet(1L); final ChessGameEntity savedChessGameEntity = new ChessGameEntity(key, chessGameEntity.getCurrentCamp(), chessGameEntity.getUserId()); diff --git a/src/test/java/chess/dao/chess/MockPieceDao.java b/src/test/java/chess/dao/chess/MockPieceDao.java index ef94cbea1ff..71294097052 100644 --- a/src/test/java/chess/dao/chess/MockPieceDao.java +++ b/src/test/java/chess/dao/chess/MockPieceDao.java @@ -25,7 +25,7 @@ public List findByChessGameId(final long chessGameId) { } @Override - public Long save(final PieceEntity pieceEntity) { + public Long insert(final PieceEntity pieceEntity) { STORAGE.put(pk.addAndGet(1L), pieceEntity); return pk.longValue(); } diff --git a/src/test/java/chess/dao/chess/PieceDaoImplTest.java b/src/test/java/chess/dao/chess/PieceDaoImplTest.java index 480e3326e3d..b20b26db849 100644 --- a/src/test/java/chess/dao/chess/PieceDaoImplTest.java +++ b/src/test/java/chess/dao/chess/PieceDaoImplTest.java @@ -18,7 +18,7 @@ void findByChessGameId() { final PieceDao pieceDao = new MockPieceDao(); final long chessGameId = 1L; final List pieceEntities = PieceEntityHelper.createPieceEntities(chessGameId); - pieceEntities.forEach(pieceDao::save); + pieceEntities.forEach(pieceDao::insert); // when final List findChessEntities = pieceDao.findByChessGameId(chessGameId); @@ -36,12 +36,12 @@ void findByChessGameId() { @Test @DisplayName("체스 게임에 해당하는 체스말의 정보를 저장한다") - void save() { + void insert() { // given final PieceDao pieceDao = new MockPieceDao(); // when - final Long savedPieceId = pieceDao.save(PieceEntity.createWithChessGameId(1L, 1, 2, + final Long savedPieceId = pieceDao.insert(PieceEntity.createWithChessGameId(1L, 1, 2, "PAWN", "WHITE")); // then @@ -57,8 +57,8 @@ void deleteByPositions() { final long chessGameId = 1L; final PieceEntity entity1 = PieceEntity.createWithChessGameId(chessGameId, 1, 1, "PAWN", "WHITE"); final PieceEntity entity2 = PieceEntity.createWithChessGameId(chessGameId, 1, 1, "PAWN", "WHITE"); - pieceDao.save(entity1); - pieceDao.save(entity2); + pieceDao.insert(entity1); + pieceDao.insert(entity2); // when pieceDao.deleteByPositions(chessGameId, entity1, entity2); @@ -76,8 +76,8 @@ void deleteByChessGameId() { final long chessGameId = 1L; final PieceEntity entity1 = PieceEntity.createWithChessGameId(chessGameId, 1, 1, "PAWN", "WHITE"); final PieceEntity entity2 = PieceEntity.createWithChessGameId(chessGameId, 1, 1, "PAWN", "WHITE"); - pieceDao.save(entity1); - pieceDao.save(entity2); + pieceDao.insert(entity1); + pieceDao.insert(entity2); // when pieceDao.deleteByChessGameId(chessGameId); diff --git a/src/test/java/chess/dao/user/MockUserDao.java b/src/test/java/chess/dao/user/MockUserDao.java index 7a3f07430f4..de37f2e7f76 100644 --- a/src/test/java/chess/dao/user/MockUserDao.java +++ b/src/test/java/chess/dao/user/MockUserDao.java @@ -20,7 +20,7 @@ public Optional findByName(final String name) { } @Override - public Long save(final String name) { + public Long insert(final String name) { STORAGE.put(pk.addAndGet(1L), new UserEntity(name)); return pk.longValue(); } diff --git a/src/test/java/chess/dao/user/UserDaoImplTest.java b/src/test/java/chess/dao/user/UserDaoImplTest.java index 911338a317a..0e46e2b59c5 100644 --- a/src/test/java/chess/dao/user/UserDaoImplTest.java +++ b/src/test/java/chess/dao/user/UserDaoImplTest.java @@ -16,7 +16,7 @@ void findByName() { // given final UserDao userDao = new MockUserDao(); final String name = "journey"; - userDao.save(name); + userDao.insert(name); final long expected = new UserEntity(1L, name).getId(); // when @@ -48,7 +48,7 @@ void insert() { final UserDao userDao = new MockUserDao(); // when - Long userId = userDao.save("journey"); + Long userId = userDao.insert("journey"); // then assertThat(userId) diff --git a/src/test/java/chess/service/ChessBoardServiceTestHandler.java b/src/test/java/chess/service/ChessBoardServiceTestHandler.java index d8686f31673..ef634327980 100644 --- a/src/test/java/chess/service/ChessBoardServiceTestHandler.java +++ b/src/test/java/chess/service/ChessBoardServiceTestHandler.java @@ -113,7 +113,7 @@ void deleteByChessGameId() { private PieceDao createPieceDao(final Long chessGameId) { final PieceDao pieceDao = new MockPieceDao(); final List pieceEntities = PieceEntityHelper.createPieceEntities(chessGameId); - pieceEntities.forEach(pieceDao::save); + pieceEntities.forEach(pieceDao::insert); return pieceDao; } diff --git a/src/test/java/chess/service/ChessGameServiceTestHandler.java b/src/test/java/chess/service/ChessGameServiceTestHandler.java index 0719145de47..25cfa801820 100644 --- a/src/test/java/chess/service/ChessGameServiceTestHandler.java +++ b/src/test/java/chess/service/ChessGameServiceTestHandler.java @@ -108,7 +108,7 @@ void deletePieces() { // given final long userId = 1L; final MockChessGameDao chessGameDao = new MockChessGameDao(); - chessGameDao.save(new ChessGameEntity("WHITE", userId)); + chessGameDao.insert(new ChessGameEntity("WHITE", userId)); final ChessGameService chessGameService = new ChessGameService(chessGameDao, new ChessBoardService(new MockPieceDao())); final PieceEntity source = PieceEntity.createWithLocation(1L, 0, 0); final PieceEntity target = PieceEntity.createWithLocation(1L, 0, 1); @@ -141,7 +141,7 @@ void clear() { private ChessGameService getChessGameService(final long userId) { final MockChessGameDao chessGameDao = new MockChessGameDao(); - final long chessGameId = chessGameDao.save(new ChessGameEntity(1L, "WHITE", userId)); + final long chessGameId = chessGameDao.insert(new ChessGameEntity(1L, "WHITE", userId)); final MockPieceDao pieceDao = getMockPieceDao(chessGameId); return new ChessGameService(chessGameDao, new ChessBoardService(pieceDao)); } @@ -149,7 +149,7 @@ private ChessGameService getChessGameService(final long userId) { private MockPieceDao getMockPieceDao(final long chessGameId) { final List pieceEntities = PieceEntityHelper.createPieceEntities(chessGameId); final MockPieceDao pieceDao = new MockPieceDao(); - pieceEntities.forEach(pieceDao::save); + pieceEntities.forEach(pieceDao::insert); return pieceDao; } } From e0bc4d989d96ad1325ec5909e8598160b9082e51 Mon Sep 17 00:00:00 2001 From: jiwon Date: Thu, 30 Mar 2023 22:11:49 +0900 Subject: [PATCH 75/76] =?UTF-8?q?fix:=20ChessGame=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20equals,=20hashcode=20=EC=9E=AC=EC=A0=95=EC=9D=98?= =?UTF-8?q?=EB=A5=BC=20=EC=82=AD=EC=A0=9C=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/chess/dao/chess/PieceDaoImpl.java | 4 +++ .../java/chess/domain/chess/ChessGame.java | 16 +---------- .../service/ChessGameServiceTestHandler.java | 27 ++++++++++++------- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/main/java/chess/dao/chess/PieceDaoImpl.java b/src/main/java/chess/dao/chess/PieceDaoImpl.java index 88048679901..627e887a29a 100644 --- a/src/main/java/chess/dao/chess/PieceDaoImpl.java +++ b/src/main/java/chess/dao/chess/PieceDaoImpl.java @@ -38,8 +38,12 @@ public Long insert(final PieceEntity pieceEntity) { @Override public void deleteByPositions(final long chessGameId, final PieceEntity... pieceEntity) { + if (pieceEntity == null) { + return; + } if (pieceEntity.length == 1) { deleteOneByPosition(chessGameId, pieceEntity[0]); + return; } final PieceEntity source = pieceEntity[0]; final PieceEntity destination = pieceEntity[1]; diff --git a/src/main/java/chess/domain/chess/ChessGame.java b/src/main/java/chess/domain/chess/ChessGame.java index b498c6fac4f..62a46e73e8f 100644 --- a/src/main/java/chess/domain/chess/ChessGame.java +++ b/src/main/java/chess/domain/chess/ChessGame.java @@ -6,7 +6,6 @@ import java.util.List; import java.util.Map; -import java.util.Objects; public final class ChessGame { private static final int ALL_KING_ALIVE_COUNT = 2; @@ -96,20 +95,7 @@ private void validatePieceExistence(final Position position) { throw new IllegalArgumentException("체스말이 존재하는 위치를 입력해 주세요."); } } - - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - final ChessGame chessGame = (ChessGame) o; - return Objects.equals(chessBoard, chessGame.chessBoard) && currentCamp == chessGame.currentCamp; - } - - @Override - public int hashCode() { - return Objects.hash(chessBoard, currentCamp); - } - + public Map getChessBoard() { return chessBoard.getBoard(); } diff --git a/src/test/java/chess/service/ChessGameServiceTestHandler.java b/src/test/java/chess/service/ChessGameServiceTestHandler.java index 25cfa801820..858eb21bdaa 100644 --- a/src/test/java/chess/service/ChessGameServiceTestHandler.java +++ b/src/test/java/chess/service/ChessGameServiceTestHandler.java @@ -6,6 +6,8 @@ import chess.domain.board.ChessBoard; import chess.domain.chess.CampType; import chess.domain.chess.ChessGame; +import chess.domain.piece.Piece; +import chess.domain.piece.move.Position; import chess.entity.ChessGameEntity; import chess.entity.PieceEntity; import org.junit.jupiter.api.DisplayName; @@ -13,6 +15,7 @@ import java.util.Collections; import java.util.List; +import java.util.Map; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -25,10 +28,11 @@ void getOrCreateChessGame_empty() { final MockChessGameDao chessGameDao = new MockChessGameDao(); final ChessGameService chessGameService = new ChessGameService( chessGameDao, new ChessBoardService(new MockPieceDao())); - final ChessGame expected = new ChessGame(CampType.WHITE); + final Map expected = new ChessGame(CampType.WHITE).getChessBoard(); // when - final ChessGame actual = chessGameService.getOrCreateChessGame(2L); + final Map actual = chessGameService.getOrCreateChessGame(2L) + .getChessBoard(); // then assertThat(actual) @@ -42,10 +46,12 @@ void getOrCreateChessGame() { final long userId = 1L; final ChessGameService chessGameService = getChessGameService(userId); final ChessBoard mockProgressBoard = ChessBoardHelper.createMockProgressBoard(); - final ChessGame expected = new ChessGame(mockProgressBoard, CampType.WHITE); + final Map expected = new ChessGame(mockProgressBoard, CampType.WHITE) + .getChessBoard(); // when - final ChessGame actual = chessGameService.getOrCreateChessGame(userId); + final Map actual = chessGameService.getOrCreateChessGame(userId) + .getChessBoard(); // then assertThat(actual) @@ -112,14 +118,17 @@ void deletePieces() { final ChessGameService chessGameService = new ChessGameService(chessGameDao, new ChessBoardService(new MockPieceDao())); final PieceEntity source = PieceEntity.createWithLocation(1L, 0, 0); final PieceEntity target = PieceEntity.createWithLocation(1L, 0, 1); + final Map expected = new ChessGame(ChessBoard.create(Collections.emptyMap()), CampType.WHITE) + .getChessBoard(); // when chessGameService.deletePieces(source, target); // then - final ChessGame actual = chessGameService.getOrCreateChessGame(1L); + final Map actual = chessGameService.getOrCreateChessGame(1L).getChessBoard(); + assertThat(actual) - .isEqualTo(new ChessGame(ChessBoard.create(Collections.emptyMap()), CampType.WHITE)); + .isEqualTo(expected); } @Test @@ -133,9 +142,9 @@ void clear() { chessGameService.clear(userId); // then - final ChessGame chessGame = chessGameService.getOrCreateChessGame(userId); - final ChessGame expected = new ChessGame(CampType.WHITE); - assertThat(chessGame) + final Map actual = chessGameService.getOrCreateChessGame(userId).getChessBoard(); + final Map expected = new ChessGame(CampType.WHITE).getChessBoard(); + assertThat(actual) .isEqualTo(expected); } From fe690b215c53adbaf800599a9eaebe22a5698ed3 Mon Sep 17 00:00:00 2001 From: jiwon Date: Thu, 30 Mar 2023 22:37:48 +0900 Subject: [PATCH 76/76] =?UTF-8?q?feat:=20MoveController=EC=97=90=20?= =?UTF-8?q?=EC=A1=B4=EC=9E=AC=ED=95=98=EB=8D=98=20db=20=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=20=EB=A1=9C=EC=A7=81=EC=9D=84=20=EC=84=9C=EB=B9=84=EC=8A=A4?= =?UTF-8?q?=EC=97=90=EA=B2=8C=20=EC=9C=84=EC=9E=84=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/status/MoveController.java | 32 ++--------- .../java/chess/service/ChessGameService.java | 26 +++++++-- .../service/ChessGameServiceTestHandler.java | 55 +++++++++---------- 3 files changed, 49 insertions(+), 64 deletions(-) diff --git a/src/main/java/chess/controller/status/MoveController.java b/src/main/java/chess/controller/status/MoveController.java index 3cd714e7a59..5871a3d6244 100644 --- a/src/main/java/chess/controller/status/MoveController.java +++ b/src/main/java/chess/controller/status/MoveController.java @@ -2,14 +2,11 @@ import chess.controller.Command; import chess.domain.chess.ChessGame; -import chess.domain.piece.Piece; import chess.domain.piece.move.Position; import chess.domain.piece.move.PositionConverter; -import chess.entity.PieceEntity; import chess.service.ChessGameService; import java.util.List; -import java.util.Map; import java.util.Optional; public final class MoveController implements Controller { @@ -49,9 +46,8 @@ public Optional findGame() { Controller move(final Command command) { validateCommand(command); - final List commands = command.getCommands(); + playChessGame(command); final ChessGame chessGame = chessGameService.getOrCreateChessGame(userId); - play(commands, chessGame); if (!chessGame.isKingAlive()) { return new StatusController(userId, chessGameService).getStatus(false); } @@ -64,31 +60,11 @@ private void validateCommand(final Command command) { } } - private void play(final List commands, final ChessGame chessGame) { + private void playChessGame(final Command command) { + final List commands = command.getCommands(); final Position source = PositionConverter.convert(commands.get(1)); final Position target = PositionConverter.convert(commands.get(2)); - chessGame.play(source, target); - savePlayInfo(source, target, chessGame); - } - - private void savePlayInfo(final Position source, final Position target, final ChessGame chessGame) { - final long chessGameId = chessGameService.getChessGameId(userId); - deletePieces(source, target, chessGameId); - savePieces(target, chessGameId, chessGame); - chessGameService.updateCurrentCamp(chessGameId, chessGame.getCurrentCamp()); + chessGameService.play(userId, source, target); } - private void deletePieces(final Position source, final Position target, final long chessGameId) { - final PieceEntity sourcePiece = PieceEntity.createWithLocation(chessGameId, source.getRank(), source.getFile()); - final PieceEntity targetPiece = PieceEntity.createWithLocation(chessGameId, target.getRank(), target.getFile()); - chessGameService.deletePieces(sourcePiece, targetPiece); - } - - private void savePieces(final Position target, final long chessGameId, final ChessGame chessGame) { - final Map chessBoard = chessGame.getChessBoard(); - final Piece piece = chessBoard.get(target); - final PieceEntity savedPiece = PieceEntity.createWithChessGameId(chessGameId, target.getRank(), - target.getFile(), piece.getPieceType().name(), piece.getCampType().name()); - chessGameService.savePiece(savedPiece); - } } diff --git a/src/main/java/chess/service/ChessGameService.java b/src/main/java/chess/service/ChessGameService.java index b11c1fbf58e..de05f8decd4 100644 --- a/src/main/java/chess/service/ChessGameService.java +++ b/src/main/java/chess/service/ChessGameService.java @@ -4,9 +4,12 @@ import chess.domain.board.ChessBoard; import chess.domain.chess.CampType; import chess.domain.chess.ChessGame; +import chess.domain.piece.Piece; +import chess.domain.piece.move.Position; import chess.entity.ChessGameEntity; import chess.entity.PieceEntity; +import java.util.Map; import java.util.Optional; public final class ChessGameService { @@ -35,16 +38,27 @@ public long getChessGameId(final long userId) { return findChessGameEntity.get().getId(); } - public void savePiece(final PieceEntity pieceEntity) { - chessBoardService.savePiece(pieceEntity); + public void play(final long userId, final Position source, final Position target) { + final ChessGame chessGame = getOrCreateChessGame(userId); + chessGame.play(source, target); + final long chessGameId = getChessGameId(userId); + deletePieces(source, target, chessGameId); + savePieces(target, chessGameId, chessGame); + chessGameDao.updateCurrentCampById(chessGameId, chessGame.getCurrentCamp()); } - public void updateCurrentCamp(final long chessGameId, final CampType currentCamp) { - chessGameDao.updateCurrentCampById(chessGameId, currentCamp); + private void deletePieces(final Position source, final Position target, final long chessGameId) { + final PieceEntity sourcePiece = PieceEntity.createWithLocation(chessGameId, source.getRank(), source.getFile()); + final PieceEntity targetPiece = PieceEntity.createWithLocation(chessGameId, target.getRank(), target.getFile()); + chessBoardService.deletePieces(sourcePiece, targetPiece); } - public void deletePieces(final PieceEntity sourcePiece, final PieceEntity targetPiece) { - chessBoardService.deletePieces(sourcePiece, targetPiece); + private void savePieces(final Position target, final long chessGameId, final ChessGame chessGame) { + final Map chessBoard = chessGame.getChessBoard(); + final Piece piece = chessBoard.get(target); + final PieceEntity savedPiece = PieceEntity.createWithChessGameId(chessGameId, target.getRank(), + target.getFile(), piece.getPieceType().name(), piece.getCampType().name()); + chessBoardService.savePiece(savedPiece); } public void clear(final long userId) { diff --git a/src/test/java/chess/service/ChessGameServiceTestHandler.java b/src/test/java/chess/service/ChessGameServiceTestHandler.java index 858eb21bdaa..893a660f19a 100644 --- a/src/test/java/chess/service/ChessGameServiceTestHandler.java +++ b/src/test/java/chess/service/ChessGameServiceTestHandler.java @@ -13,7 +13,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -74,61 +74,56 @@ void getChessGameId() { } @Test - @DisplayName("체스말 정보를 바탕으로 체스말을 저장한다") - void savePiece() { + @DisplayName("게임을 플레이하면, 시작 위치에 존재하는 체스말을 제거한다") + void play_deletePieces() { // given final long userId = 1L; final ChessGameService chessGameService = getChessGameService(userId); // when - chessGameService.savePiece(PieceEntity.createWithChessGameId(1L, 1, 1, - "PAWN", "WHITE")); + chessGameService.play(1L, new Position(1, 0), new Position(2, 0)); // then - final long chessGameId = chessGameService.getChessGameId(1L); - assertThat(chessGameId) - .isEqualTo(1L); + final Map expected = new HashMap<>(chessGameService.getOrCreateChessGame(userId).getChessBoard()); + expected.remove(new Position(1, 0)); + final Map actual = chessGameService.getOrCreateChessGame(1L).getChessBoard(); + + assertThat(actual) + .isEqualTo(expected); } @Test - @DisplayName("체스 게임 아이디에 해당하는 진영 정보를 업데이트한다.") - void updateCurrentCamp() { + @DisplayName("게임을 플레이하면, 체스말 정보를 바탕으로 체스말을 저장한다") + void play_savePieces() { // given final long userId = 1L; final ChessGameService chessGameService = getChessGameService(userId); - final CampType changedCamp = CampType.BLACK; // when - chessGameService.updateCurrentCamp(1L, changedCamp); + chessGameService.play(1L, new Position(1, 1), new Position(2, 1)); // then - final ChessGame chessGame = chessGameService.getOrCreateChessGame(1L); - final CampType campType = chessGame.getCurrentCamp(); - assertThat(campType) - .isEqualTo(changedCamp); + final long chessGameId = chessGameService.getChessGameId(1L); + assertThat(chessGameId) + .isEqualTo(1L); } @Test - @DisplayName("입력받은 위치에 해당하는 체스말을 제거한다") - void deletePieces() { + @DisplayName("게임을 플레이하면, 체스 게임 아이디에 해당하는 진영 정보를 업데이트한다.") + void play_updateCurrentCamp() { // given final long userId = 1L; - final MockChessGameDao chessGameDao = new MockChessGameDao(); - chessGameDao.insert(new ChessGameEntity("WHITE", userId)); - final ChessGameService chessGameService = new ChessGameService(chessGameDao, new ChessBoardService(new MockPieceDao())); - final PieceEntity source = PieceEntity.createWithLocation(1L, 0, 0); - final PieceEntity target = PieceEntity.createWithLocation(1L, 0, 1); - final Map expected = new ChessGame(ChessBoard.create(Collections.emptyMap()), CampType.WHITE) - .getChessBoard(); + final ChessGameService chessGameService = getChessGameService(userId); + final CampType changedCamp = CampType.BLACK; // when - chessGameService.deletePieces(source, target); + chessGameService.play(1L, new Position(1, 1), new Position(2, 1)); // then - final Map actual = chessGameService.getOrCreateChessGame(1L).getChessBoard(); - - assertThat(actual) - .isEqualTo(expected); + final ChessGame chessGame = chessGameService.getOrCreateChessGame(1L); + final CampType campType = chessGame.getCurrentCamp(); + assertThat(campType) + .isEqualTo(changedCamp); } @Test