From 257a93372ceefa7d5d43eeaeffb7afce61365eab Mon Sep 17 00:00:00 2001 From: 3Juhwan <13selfesteem91@naver.com> Date: Sun, 24 Mar 2024 16:44:20 +0900 Subject: [PATCH 01/94] =?UTF-8?q?[1,=202=EB=8B=A8=EA=B3=84=20-=20=EC=B2=B4?= =?UTF-8?q?=EC=8A=A4]=20=EB=A7=9D=EC=B5=B8(=EA=B9=80=EC=A3=BC=ED=99=98)=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EC=A0=9C=EC=B6=9C=ED=95=A9=EB=8B=88?= =?UTF-8?q?=EB=8B=A4.=20(#712)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: 기능 목록 추가 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 킹이 여덟 방향으로 움직이는지 확인하는 기능 추가 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 비숍이 대각선 방향으로 움직이는지 확인하는 기능 추가 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * test: king이 두 칸 이상 움직일 수 없는지 테스트 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 체스 말 타입 추가 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 포지션 객체 추가 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * refactor: 2단계 관련 클래스 삭제 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 체스판에 말을 놓는 기능 추가 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: file 클래스 추가 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: rank 클래스 추가 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 이전, 다음 file을 반환하는 기능 추가 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 움직임의 방향성을 계산하는 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 이동 방향을 반환하는 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 다음 포지션을 반환하는 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 피스가 움직이는 경로를 반환하는 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 킹, 퀸 이동 검증 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * refactor: 이동 검증 클래스 추상화 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 룩 이동 검증 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 비숍, 나이트 이동 검증 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * style: 테스트 개행 추가 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 피스에 이동 경로 검증 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * refactor: 공통 로직 추상 클래스로 추상화 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 블랙 폰, 화이트 폰 추가 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * refactor: 포지션 간의 경로를 계산하는 기능을 이전 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * refactor: piece를 추상화하여 king 세부 사항 재구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * refactor: queen 세부 사항 재구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * refactor: bishop 세부 사항 재구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * refactor: knight 세부 사항 재구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * refactor: rook 세부 사항 재구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 중립 컬러, 컬러 확인 기능 추가 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: empty 기물 추가 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: pawn 세부 사항 재구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 초기 체스보드 생성하는 팩토리 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: move 커멘드 추가 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 피스를 움직이는 체스보드 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 체스 보드 출력 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 커맨드명으로 커맨드 찾는 기능 추가 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 컨트롤러 추가 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 기물 타입 추가 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * refactor: 중복 코드 리팩토링 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * docs: 기능 목록 수정 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Nam Gi Beom * feat: 두 file 사이의 file들을 찾는 기능 추가 * feat: 두 rank 사이의 rank들을 찾는 기능 추가 * refactor: 두 position 사이의 경로를 찾는 기능 분리 * refactor: 피스를 움직이는 기능 내부 메서드 분리 * test: extract 삭제 * refactor: 아군 색깔인지 판단하는 하는 기능 추상화 * refactor: 폰이 아닌 피스들에 대한 추상화, 리팩터링 * refactor: 피스 프로퍼티 메서드명 수정 * refactor: 폰을 색상에 따라 다르게 구현 * refactor: 폰 공통 로직 추상화 * style: final 추가, 예외 메시지 수정, 메서드명 수정 * style: final 추가, 메서드 순서 변경 * style: 개행 수정, 상수 분리 * refactor: 예외 처리 디테일 수정 * refactor: 경로가 막혔는지 확인하는 기능을 Route 클래스로 분리 * refactor: 커맨트 패턴 적용 * refactor: view, controller에 커맨드 적용, 예외가 발생해도 종료되지 않게 수정 * test: 예외 메시지 수정 * feat: 턴 개념 추가 * style: 테스트 변수명 수정 resource -> source * style: 폰 테스트를 색상에 따라 분리 * feat: 게임에 턴 적용 * refactor: MessageResolver 추가 * feat: 각 명령어 별 유효성 검증 추가 * fix: 출발 지점에 피스가 존재하지 않는 경우에 예외 발생 * fix: 8번째 rank가 출력되지 않는 버그 수정 * style: 폰 움직임 거리에 대하 상수명 수정 * style: 예외 메시지 수정 * style: 사용하지 않는 상수 제거 * docs: 추가 룰에 대한 문서 수정, 구현한 사항 체크 * style: 누락된 final 키워드 추가 * style: 필드 변수를 소문자로 수정 * refactor: 턴을 ChessBoard가 직접 관리하게 수정 * test: 개행 추가, 빈 리스트 검증에 isEmpty() 메서드 사용 --------- Co-authored-by: Nam Gi Beom --- README.md | 97 ++++++- src/main/java/Application.java | 11 + src/main/java/controller/ChessController.java | 46 ++++ src/main/java/controller/command/Command.java | 10 + .../java/controller/command/EndOnCommand.java | 16 ++ .../controller/command/MoveOnCommand.java | 30 +++ .../controller/command/StartOnCommand.java | 16 ++ src/main/java/domain/board/ChessBoard.java | 82 ++++++ .../java/domain/board/ChessBoardFactory.java | 44 +++ src/main/java/domain/board/Turn.java | 27 ++ src/main/java/domain/piece/Color.java | 19 ++ src/main/java/domain/piece/Empty.java | 29 ++ src/main/java/domain/piece/Piece.java | 11 + src/main/java/domain/piece/Type.java | 10 + .../java/domain/piece/nonpawn/Bishop.java | 23 ++ src/main/java/domain/piece/nonpawn/King.java | 23 ++ .../java/domain/piece/nonpawn/Knight.java | 23 ++ .../domain/piece/nonpawn/NonPawnPiece.java | 32 +++ src/main/java/domain/piece/nonpawn/Queen.java | 23 ++ src/main/java/domain/piece/nonpawn/Rook.java | 23 ++ .../java/domain/piece/pawn/BlackPawn.java | 30 +++ .../java/domain/piece/pawn/PawnPiece.java | 79 ++++++ .../java/domain/piece/pawn/WhitePawn.java | 30 +++ src/main/java/domain/position/File.java | 66 +++++ src/main/java/domain/position/Position.java | 102 +++++++ src/main/java/domain/position/Rank.java | 58 ++++ src/main/java/domain/position/Route.java | 66 +++++ src/main/java/view/Command.java | 17 ++ src/main/java/view/InputView.java | 53 ++++ src/main/java/view/MessageResolver.java | 80 ++++++ src/main/java/view/OutputView.java | 24 ++ .../java/domain/board/ChessBoardTest.java | 120 +++++++++ src/test/java/domain/board/TurnTest.java | 45 ++++ .../java/domain/piece/nonpawn/BishopTest.java | 92 +++++++ .../java/domain/piece/nonpawn/KingTest.java | 60 +++++ .../java/domain/piece/nonpawn/KnightTest.java | 82 ++++++ .../java/domain/piece/nonpawn/QueenTest.java | 92 +++++++ .../java/domain/piece/nonpawn/RookTest.java | 102 +++++++ .../java/domain/piece/pawn/BlackPawnTest.java | 133 +++++++++ .../java/domain/piece/pawn/WhitePawnTest.java | 133 +++++++++ src/test/java/domain/position/FileTest.java | 41 +++ .../java/domain/position/PositionTest.java | 4 + src/test/java/domain/position/RankTest.java | 48 ++++ src/test/java/domain/position/RouteTest.java | 255 ++++++++++++++++++ 44 files changed, 2404 insertions(+), 3 deletions(-) create mode 100644 src/main/java/Application.java create mode 100644 src/main/java/controller/ChessController.java create mode 100644 src/main/java/controller/command/Command.java create mode 100644 src/main/java/controller/command/EndOnCommand.java create mode 100644 src/main/java/controller/command/MoveOnCommand.java create mode 100644 src/main/java/controller/command/StartOnCommand.java create mode 100644 src/main/java/domain/board/ChessBoard.java create mode 100644 src/main/java/domain/board/ChessBoardFactory.java create mode 100644 src/main/java/domain/board/Turn.java create mode 100644 src/main/java/domain/piece/Color.java create mode 100644 src/main/java/domain/piece/Empty.java create mode 100644 src/main/java/domain/piece/Piece.java create mode 100644 src/main/java/domain/piece/Type.java create mode 100644 src/main/java/domain/piece/nonpawn/Bishop.java create mode 100644 src/main/java/domain/piece/nonpawn/King.java create mode 100644 src/main/java/domain/piece/nonpawn/Knight.java create mode 100644 src/main/java/domain/piece/nonpawn/NonPawnPiece.java create mode 100644 src/main/java/domain/piece/nonpawn/Queen.java create mode 100644 src/main/java/domain/piece/nonpawn/Rook.java create mode 100644 src/main/java/domain/piece/pawn/BlackPawn.java create mode 100644 src/main/java/domain/piece/pawn/PawnPiece.java create mode 100644 src/main/java/domain/piece/pawn/WhitePawn.java create mode 100644 src/main/java/domain/position/File.java create mode 100644 src/main/java/domain/position/Position.java create mode 100644 src/main/java/domain/position/Rank.java create mode 100644 src/main/java/domain/position/Route.java create mode 100644 src/main/java/view/Command.java create mode 100644 src/main/java/view/InputView.java create mode 100644 src/main/java/view/MessageResolver.java create mode 100644 src/main/java/view/OutputView.java create mode 100644 src/test/java/domain/board/ChessBoardTest.java create mode 100644 src/test/java/domain/board/TurnTest.java create mode 100644 src/test/java/domain/piece/nonpawn/BishopTest.java create mode 100644 src/test/java/domain/piece/nonpawn/KingTest.java create mode 100644 src/test/java/domain/piece/nonpawn/KnightTest.java create mode 100644 src/test/java/domain/piece/nonpawn/QueenTest.java create mode 100644 src/test/java/domain/piece/nonpawn/RookTest.java create mode 100644 src/test/java/domain/piece/pawn/BlackPawnTest.java create mode 100644 src/test/java/domain/piece/pawn/WhitePawnTest.java create mode 100644 src/test/java/domain/position/FileTest.java create mode 100644 src/test/java/domain/position/PositionTest.java create mode 100644 src/test/java/domain/position/RankTest.java create mode 100644 src/test/java/domain/position/RouteTest.java diff --git a/README.md b/README.md index 8102f91c870..2133d8c8fc6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,98 @@ # java-chess -체스 미션 저장소 +## 기능 요구사항 -## 우아한테크코스 코드리뷰 +### 기물 공통 -- [온라인 코드 리뷰 과정](https://github.com/woowacourse/woowacourse-docs/blob/master/maincourse/README.md) +- [x] 움직이지 않을 경우 예외가 발생한다. + +### Pawn + +- [x] 앞에 다른 기물이 없을 때 한 칸 이동한다. + - [x] **[예외]** 앞에 다른 기물이 있을 때 + - [x] **[예외]** 두 칸 이상 이동할 때 +- [x] 처음 위치일 때 앞으로 두 칸 이동할 수 있다. + - [x] **[예외]** 앞에 다른 기물이 있을 때 (아군, 적군) + - [x] **[예외]** 처음 위치가 아닐 때 + - 블랙 : 7 rank + - 화이트 : 2 rank +- [x] 대각선에 상대 기물이 있으면 대각선으로 이동한다. + - [x] **[예외]** 대각선에 상대 기물이 없을 때 + - [x] **[예외]** 두 칸 이상 이동할 때 +- [x] 뒤로 이동할 수 없다. + +### Knight + +- [x] L자로 이동한다. + - [x] **[예외]** L자로 이동하지 않을 때 +- [x] 이동 경로에 다른 기물이 있어도 뛰어 넘을 수 있다. +- [x] 도착지에 상대 기물이 있으면 잡을 수 있다. + - [x] **[예외]** 도착지에 아군 기물이 있을 때 + +### Bishop + +- [x] 대각선으로 이동할 수 있다. + - [x] **[예외]** 대각선으로 이동하지 않을 때 +- [x] 이동 경로에 다른 기물이 있으면 이동할 수 없다. +- [x] 도착지에 상대 기물이 있으면 잡을 수 있다. + - [x] **[예외]** 도착지에 아군 기물이 있을 때 + +### Rook + +- [x] 수직, 수평으로 이동할 수 있다. + - [x] **[예외]** 수직, 수평으로 이동하지 않을 때 +- [x] 이동 경로에 다른 기물이 있으면 이동할 수 없다. +- [x] 도착지에 상대 기물이 있으면 잡을 수 있다. + - [x] **[예외]** 도착지에 아군 기물이 있을 때 + +### Queen + +- [x] 수평, 수직, 대각선으로 이동할 수 있다. + - [x] **[예외]** 수평, 수직, 대각선으로 이동하지 않을 때 +- [x] 이동 경로에 다른 기물이 있으면 이동할 수 없다. +- [x] 도착지에 상대 기물이 있으면 잡을 수 있다. + - [x] **[예외]** 도착지에 아군 기물이 있을 때 + +### King + +- [x] 수평, 수직, 대각선으로 한 칸 이동할 수 있다. + - [x] **[예외]** 수평, 수직, 대각선으로 이동하지 않을 때 + - [x] **[예외]** 두 칸 이상 이동할 때 +- [x] 도착지에 상대 기물이 있으면 잡을 수 있다. + - [x] **[예외]** 도착지에 아군 기물이 있을 때 + +### 체스판 + +- [x] 포지션이 체스판 범위 내인지 확인한다. + - [x] **[예외]** 범위를 벗어났을 때 +- [x] 기물의 이동 경로에 다른 기물이 있는지 확인한다. + - [x] **[예외]** 경로에 다른 기물이 있을 때 +- [x] 자신의 턴인지 확인한다. + - [x] **[예외]** 상대의 턴일 때 +- [x] 기물을 이동한다. + +### 체스판 팩토리 + +- [x] 기물을 생성한다. +- [x] 체스판을 생성한다. + +### 커맨드 + +- [x] start는 게임을 시작한다. +- [x] end는 게임을 종료한다. +- [x] move는 기물을 이동한다. + +### 입력 + +- [x] 커맨드를 입력받는다. + +### 출력 + +- [x] 체스판을 출력한다. + - [x] 아래(백, 소문자), 위(흑, 대문자) + +### 추가 룰 + +- [ ] 프로모션 : 폰이 상대 마지막 진영까지 도달하면 다른 기물로 변경할 수 있다. +- [ ] 앙파상 +- [ ] 캐슬링 diff --git a/src/main/java/Application.java b/src/main/java/Application.java new file mode 100644 index 00000000000..ed9b2b5a47d --- /dev/null +++ b/src/main/java/Application.java @@ -0,0 +1,11 @@ +import controller.ChessController; +import view.InputView; +import view.MessageResolver; +import view.OutputView; + +public class Application { + public static void main(String[] args) { + ChessController chessController = new ChessController(new InputView(), new OutputView(new MessageResolver())); + chessController.start(); + } +} diff --git a/src/main/java/controller/ChessController.java b/src/main/java/controller/ChessController.java new file mode 100644 index 00000000000..c64185f254d --- /dev/null +++ b/src/main/java/controller/ChessController.java @@ -0,0 +1,46 @@ +package controller; + +import controller.command.Command; +import domain.board.ChessBoard; +import domain.board.ChessBoardFactory; +import view.InputView; +import view.OutputView; + +public class ChessController { + private final InputView inputView; + private final OutputView outputView; + + public ChessController(InputView inputView, OutputView outputView) { + this.inputView = inputView; + this.outputView = outputView; + } + + public void start() { + outputView.printGameGuideMessage(); + final ChessBoard board = ChessBoardFactory.createInitialChessBoard(); + + Command command = readStartCommandUntilValid(); + while (command.isNotEnded()) { + command.execute(board, outputView); + command = readCommandUntilValid(); + } + } + + private Command readStartCommandUntilValid() { + try { + return inputView.readStartCommand(); + } catch (Exception e) { + outputView.printErrorMessage(e.getMessage()); + return readStartCommandUntilValid(); + } + } + + private Command readCommandUntilValid() { + try { + return inputView.readCommand(); + } catch (Exception e) { + outputView.printErrorMessage(e.getMessage()); + return readCommandUntilValid(); + } + } +} diff --git a/src/main/java/controller/command/Command.java b/src/main/java/controller/command/Command.java new file mode 100644 index 00000000000..4afdb91a1f0 --- /dev/null +++ b/src/main/java/controller/command/Command.java @@ -0,0 +1,10 @@ +package controller.command; + +import domain.board.ChessBoard; +import view.OutputView; + +public interface Command { + void execute(ChessBoard board, OutputView outputView); + + boolean isNotEnded(); +} diff --git a/src/main/java/controller/command/EndOnCommand.java b/src/main/java/controller/command/EndOnCommand.java new file mode 100644 index 00000000000..3633dddd555 --- /dev/null +++ b/src/main/java/controller/command/EndOnCommand.java @@ -0,0 +1,16 @@ +package controller.command; + +import domain.board.ChessBoard; +import view.OutputView; + +public class EndOnCommand implements Command { + @Override + public void execute(final ChessBoard board, final OutputView outputView) { + + } + + @Override + public boolean isNotEnded() { + return false; + } +} diff --git a/src/main/java/controller/command/MoveOnCommand.java b/src/main/java/controller/command/MoveOnCommand.java new file mode 100644 index 00000000000..afe5612b68f --- /dev/null +++ b/src/main/java/controller/command/MoveOnCommand.java @@ -0,0 +1,30 @@ +package controller.command; + +import domain.board.ChessBoard; +import domain.position.Position; +import view.OutputView; + +public class MoveOnCommand implements Command { + private final Position source; + private final Position target; + + public MoveOnCommand(final Position source, final Position target) { + this.source = source; + this.target = target; + } + + @Override + public void execute(final ChessBoard board, final OutputView outputView) { + try { + board.move(source, target); + outputView.printBoard(board); + } catch (Exception e) { + outputView.printErrorMessage(e.getMessage()); + } + } + + @Override + public boolean isNotEnded() { + return true; + } +} diff --git a/src/main/java/controller/command/StartOnCommand.java b/src/main/java/controller/command/StartOnCommand.java new file mode 100644 index 00000000000..b900ef6e972 --- /dev/null +++ b/src/main/java/controller/command/StartOnCommand.java @@ -0,0 +1,16 @@ +package controller.command; + +import domain.board.ChessBoard; +import view.OutputView; + +public class StartOnCommand implements Command { + @Override + public void execute(final ChessBoard board, final OutputView outputView) { + outputView.printBoard(board); + } + + @Override + public boolean isNotEnded() { + return true; + } +} diff --git a/src/main/java/domain/board/ChessBoard.java b/src/main/java/domain/board/ChessBoard.java new file mode 100644 index 00000000000..328165e02e7 --- /dev/null +++ b/src/main/java/domain/board/ChessBoard.java @@ -0,0 +1,82 @@ +package domain.board; + +import domain.piece.Color; +import domain.piece.Empty; +import domain.piece.Piece; +import domain.position.Position; +import domain.position.Route; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class ChessBoard { + private final Map board; + private Color turn; + + private ChessBoard(Map board, Color color) { + this.board = board; + this.turn = color; + } + + public ChessBoard(Map board) { + this(new HashMap<>(board), Color.WHITE); + } + + public void move(final Position source, final Position target) { + validateEmptyPiece(source); + validateTurn(source); + validateEmptyRoute(source, target); + validateLegalMove(source, target); + movePiece(source, target); + changeTurn(); + } + + private void validateEmptyPiece(final Position source) { + final Piece piece = findPieceByPosition(source); + if (piece.color().isNeutrality()) { + throw new IllegalArgumentException("피스가 없습니다."); + } + } + + private void validateTurn(final Position source) { + final Piece piece = findPieceByPosition(source); + if (this.turn.isOpposite(piece.color())) { + throw new IllegalArgumentException("상대 턴입니다."); + } + } + + private void validateEmptyRoute(final Position source, final Position target) { + final Route route = Route.create(source, target); + if (route.isBlocked(board)) { + throw new IllegalArgumentException("중간에 말이 있어서 이동할 수 없습니다."); + } + } + + private void validateLegalMove(final Position source, final Position target) { + final Piece resourcePiece = findPieceByPosition(source); + resourcePiece.validateMovement(source, target, findPieceByPosition(target)); + } + + private void movePiece(final Position source, final Position target) { + final Piece piece = findPieceByPosition(source); + board.remove(source); + board.put(target, piece); + } + + private void changeTurn() { + if (this.turn.isBlack()) { + this.turn = Color.WHITE; + return; + } + this.turn = Color.BLACK; + } + + private Piece findPieceByPosition(final Position position) { + return board.getOrDefault(position, Empty.getInstance()); + } + + public Map getBoard() { + return Collections.unmodifiableMap(board); + } +} diff --git a/src/main/java/domain/board/ChessBoardFactory.java b/src/main/java/domain/board/ChessBoardFactory.java new file mode 100644 index 00000000000..cff59d6894b --- /dev/null +++ b/src/main/java/domain/board/ChessBoardFactory.java @@ -0,0 +1,44 @@ +package domain.board; + +import domain.piece.Color; +import domain.piece.Piece; +import domain.piece.nonpawn.Bishop; +import domain.piece.nonpawn.King; +import domain.piece.nonpawn.Knight; +import domain.piece.nonpawn.Queen; +import domain.piece.nonpawn.Rook; +import domain.piece.pawn.BlackPawn; +import domain.piece.pawn.WhitePawn; +import domain.position.File; +import domain.position.Position; +import domain.position.Rank; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ChessBoardFactory { + private static final int SPECIAL_PIECE_SIZE = 8; + private static final List whiteSpecialPieces = List.of( + new Rook(Color.WHITE), new Knight(Color.WHITE), new Bishop(Color.WHITE), new Queen(Color.WHITE), + new King(Color.WHITE), new Bishop(Color.WHITE), new Knight(Color.WHITE), new Rook(Color.WHITE) + ); + private static final List blackSpecialPieces = List.of( + new Rook(Color.BLACK), new Knight(Color.BLACK), new Bishop(Color.BLACK), new Queen(Color.BLACK), + new King(Color.BLACK), new Bishop(Color.BLACK), new Knight(Color.BLACK), new Rook(Color.BLACK) + ); + + private ChessBoardFactory() { + } + + public static ChessBoard createInitialChessBoard() { + final Map pieceMap = new HashMap<>(); + for (int order = 0; order < SPECIAL_PIECE_SIZE; order++) { + pieceMap.put(new Position(File.fromOrder(order), Rank.EIGHT), blackSpecialPieces.get(order)); + pieceMap.put(new Position(File.fromOrder(order), Rank.SEVEN), new BlackPawn()); + pieceMap.put(new Position(File.fromOrder(order), Rank.TWO), new WhitePawn()); + pieceMap.put(new Position(File.fromOrder(order), Rank.ONE), whiteSpecialPieces.get(order)); + } + return new ChessBoard(pieceMap); + } +} diff --git a/src/main/java/domain/board/Turn.java b/src/main/java/domain/board/Turn.java new file mode 100644 index 00000000000..637ce166a34 --- /dev/null +++ b/src/main/java/domain/board/Turn.java @@ -0,0 +1,27 @@ +package domain.board; + +import domain.piece.Color; + +public class Turn { + private Color color; + + private Turn(final Color color) { + this.color = color; + } + + Turn() { + this(Color.WHITE); + } + + void flip() { + if (this.color.isBlack()) { + this.color = Color.WHITE; + return; + } + this.color = Color.BLACK; + } + + boolean isOpponentTurn(final Color color) { + return this.color != color && !color.isNeutrality(); + } +} diff --git a/src/main/java/domain/piece/Color.java b/src/main/java/domain/piece/Color.java new file mode 100644 index 00000000000..31242149623 --- /dev/null +++ b/src/main/java/domain/piece/Color.java @@ -0,0 +1,19 @@ +package domain.piece; + +public enum Color { + WHITE, + BLACK, + NEUTRALITY; + + public boolean isBlack() { + return this == BLACK; + } + + public boolean isNeutrality() { + return this == NEUTRALITY; + } + + public boolean isOpposite(final Color color) { + return this != color && !color.isNeutrality(); + } +} diff --git a/src/main/java/domain/piece/Empty.java b/src/main/java/domain/piece/Empty.java new file mode 100644 index 00000000000..25c621cba28 --- /dev/null +++ b/src/main/java/domain/piece/Empty.java @@ -0,0 +1,29 @@ +package domain.piece; + +import domain.position.Position; + +public class Empty implements Piece { + private static final Empty INSTANCE = new Empty(); + + private Empty() { + } + + public static Empty getInstance() { + return INSTANCE; + } + + @Override + public void validateMovement(final Position resource, final Position target, final Piece other) { + throw new UnsupportedOperationException("Empty는 움직일 수 없습니다."); + } + + @Override + public Color color() { + return Color.NEUTRALITY; + } + + @Override + public Type type() { + throw new UnsupportedOperationException("Empty는 타입이 없습니다."); + } +} diff --git a/src/main/java/domain/piece/Piece.java b/src/main/java/domain/piece/Piece.java new file mode 100644 index 00000000000..4cda19b161f --- /dev/null +++ b/src/main/java/domain/piece/Piece.java @@ -0,0 +1,11 @@ +package domain.piece; + +import domain.position.Position; + +public interface Piece { + void validateMovement(Position source, Position target, Piece other); + + Color color(); + + Type type(); +} diff --git a/src/main/java/domain/piece/Type.java b/src/main/java/domain/piece/Type.java new file mode 100644 index 00000000000..0301c9f2528 --- /dev/null +++ b/src/main/java/domain/piece/Type.java @@ -0,0 +1,10 @@ +package domain.piece; + +public enum Type { + KING, + QUEEN, + ROOK, + BISHOP, + KNIGHT, + PAWN; +} diff --git a/src/main/java/domain/piece/nonpawn/Bishop.java b/src/main/java/domain/piece/nonpawn/Bishop.java new file mode 100644 index 00000000000..27aa984d683 --- /dev/null +++ b/src/main/java/domain/piece/nonpawn/Bishop.java @@ -0,0 +1,23 @@ +package domain.piece.nonpawn; + +import domain.piece.Color; +import domain.piece.Type; +import domain.position.Position; + +public class Bishop extends NonPawnPiece { + public Bishop(final Color color) { + super(color); + } + + @Override + protected void validateDirection(final Position source, final Position target) { + if (!source.isDiagonalAt(target)) { + throw new IllegalArgumentException("비숍은 대각선 방향으로만 이동할 수 있습니다."); + } + } + + @Override + public Type type() { + return Type.BISHOP; + } +} diff --git a/src/main/java/domain/piece/nonpawn/King.java b/src/main/java/domain/piece/nonpawn/King.java new file mode 100644 index 00000000000..90ae058ea8c --- /dev/null +++ b/src/main/java/domain/piece/nonpawn/King.java @@ -0,0 +1,23 @@ +package domain.piece.nonpawn; + +import domain.piece.Color; +import domain.piece.Type; +import domain.position.Position; + +public class King extends NonPawnPiece { + public King(final Color color) { + super(color); + } + + @Override + protected void validateDirection(final Position source, final Position target) { + if (!source.isAdjacentAt(target)) { + throw new IllegalArgumentException("킹은 한 번에 1칸만 이동할 수 있습니다."); + } + } + + @Override + public Type type() { + return Type.KING; + } +} diff --git a/src/main/java/domain/piece/nonpawn/Knight.java b/src/main/java/domain/piece/nonpawn/Knight.java new file mode 100644 index 00000000000..86f1474ab59 --- /dev/null +++ b/src/main/java/domain/piece/nonpawn/Knight.java @@ -0,0 +1,23 @@ +package domain.piece.nonpawn; + +import domain.piece.Color; +import domain.piece.Type; +import domain.position.Position; + +public class Knight extends NonPawnPiece { + public Knight(final Color color) { + super(color); + } + + @Override + protected void validateDirection(final Position source, final Position target) { + if (!source.isKnightPositionAt(target)) { + throw new IllegalArgumentException("나이트는 L자 방향으로만 이동할 수 있습니다."); + } + } + + @Override + public Type type() { + return Type.KNIGHT; + } +} diff --git a/src/main/java/domain/piece/nonpawn/NonPawnPiece.java b/src/main/java/domain/piece/nonpawn/NonPawnPiece.java new file mode 100644 index 00000000000..5e092040fe9 --- /dev/null +++ b/src/main/java/domain/piece/nonpawn/NonPawnPiece.java @@ -0,0 +1,32 @@ +package domain.piece.nonpawn; + +import domain.piece.Color; +import domain.piece.Piece; +import domain.position.Position; + +public abstract class NonPawnPiece implements Piece { + private final Color color; + + protected NonPawnPiece(final Color color) { + this.color = color; + } + + @Override + public final void validateMovement(final Position source, final Position target, final Piece other) { + validateColorDifference(other); + validateDirection(source, target); + } + + private void validateColorDifference(final Piece other) { + if (this.color() == other.color()) { + throw new IllegalArgumentException("같은 팀의 말을 잡을 수 없습니다."); + } + } + + protected abstract void validateDirection(final Position source, final Position target); + + @Override + public Color color() { + return color; + } +} diff --git a/src/main/java/domain/piece/nonpawn/Queen.java b/src/main/java/domain/piece/nonpawn/Queen.java new file mode 100644 index 00000000000..abc8f7d9332 --- /dev/null +++ b/src/main/java/domain/piece/nonpawn/Queen.java @@ -0,0 +1,23 @@ +package domain.piece.nonpawn; + +import domain.piece.Color; +import domain.piece.Type; +import domain.position.Position; + +public class Queen extends NonPawnPiece { + public Queen(final Color color) { + super(color); + } + + @Override + protected void validateDirection(final Position source, final Position target) { + if (!source.isDiagonalAt(target) && !source.isStraightAt(target)) { + throw new IllegalArgumentException("퀸은 대각선, 수평, 수직 방향으로만 이동할 수 있습니다."); + } + } + + @Override + public Type type() { + return Type.QUEEN; + } +} diff --git a/src/main/java/domain/piece/nonpawn/Rook.java b/src/main/java/domain/piece/nonpawn/Rook.java new file mode 100644 index 00000000000..eb53fe5c98c --- /dev/null +++ b/src/main/java/domain/piece/nonpawn/Rook.java @@ -0,0 +1,23 @@ +package domain.piece.nonpawn; + +import domain.piece.Color; +import domain.piece.Type; +import domain.position.Position; + +public class Rook extends NonPawnPiece { + public Rook(final Color color) { + super(color); + } + + @Override + protected void validateDirection(final Position source, final Position target) { + if (!source.isStraightAt(target)) { + throw new IllegalArgumentException("룩은 수평, 수직 방향으로만 이동할 수 있습니다."); + } + } + + @Override + public Type type() { + return Type.ROOK; + } +} diff --git a/src/main/java/domain/piece/pawn/BlackPawn.java b/src/main/java/domain/piece/pawn/BlackPawn.java new file mode 100644 index 00000000000..6526648ccba --- /dev/null +++ b/src/main/java/domain/piece/pawn/BlackPawn.java @@ -0,0 +1,30 @@ +package domain.piece.pawn; + +import domain.piece.Color; +import domain.position.Position; +import domain.position.Rank; + +public class BlackPawn extends PawnPiece { + private static final Rank INITIAL_RANK = Rank.SEVEN; + + public BlackPawn() { + super(Color.BLACK); + } + + @Override + protected void validateForwardMovement(final Position source, final Position target) { + if (!source.isUpperRankThan(target)) { + throw new IllegalArgumentException("폰은 앞으로 이동해야 합니다."); + } + } + + @Override + protected boolean isAtSameRank(final Position source) { + return source.isAtSameRank(INITIAL_RANK); + } + + @Override + public Color color() { + return Color.BLACK; + } +} diff --git a/src/main/java/domain/piece/pawn/PawnPiece.java b/src/main/java/domain/piece/pawn/PawnPiece.java new file mode 100644 index 00000000000..fea04d2ff36 --- /dev/null +++ b/src/main/java/domain/piece/pawn/PawnPiece.java @@ -0,0 +1,79 @@ +package domain.piece.pawn; + +import domain.piece.Color; +import domain.piece.Piece; +import domain.piece.Type; +import domain.position.Position; + +public abstract class PawnPiece implements Piece { + private static final int INITIAL_MOVE_DISTANCE = 2; + private static final int NORMAL_MOVE_DISTANCE = 1; + + private final Color color; + + protected PawnPiece(Color color) { + this.color = color; + } + + public final void validateMovement(final Position source, final Position target, final Piece other) { + validateColorDifference(other); + validateForwardMovement(source, target); + validateFawnMovement(source, target, other); + } + + private void validateColorDifference(final Piece other) { + if (this.color() == other.color()) { + throw new IllegalArgumentException("같은 팀의 말을 잡을 수 없습니다."); + } + } + + protected abstract void validateForwardMovement(final Position source, final Position target); + + private void validateFawnMovement(final Position source, final Position target, final Piece other) { + if (!isPawnMovement(source, target, other)) { + throw new IllegalArgumentException("잘못된 방향으로 이동하고 있습니다."); + } + } + + private boolean isPawnMovement(final Position source, final Position target, final Piece other) { + return isMovingTwoDistanceForward(source, target, other) || + isMovingOneDistanceForward(source, target, other) || + isMovingOneDistanceDiagonal(source, target, other); + } + + private boolean isMovingTwoDistanceForward(final Position source, final Position target, final Piece other) { + return isAtSameRank(source) && source.isStraightAt(target) + && source.isDistanceAt(target, INITIAL_MOVE_DISTANCE) && nonPieceExist(other); + } + + protected abstract boolean isAtSameRank(final Position source); + + private boolean isMovingOneDistanceForward(final Position source, final Position target, final Piece other) { + return source.isStraightAt(target) && source.isDistanceAt(target, NORMAL_MOVE_DISTANCE) && nonPieceExist(other); + } + + private boolean isMovingOneDistanceDiagonal(final Position source, final Position target, final Piece other) { + return source.isDiagonalAt(target) && source.isAdjacentAt(target) && isOpposite(other); + } + + private boolean nonPieceExist(Piece other) { + return other.color().isNeutrality(); + } + + private boolean isOpposite(Piece other) { + if (nonPieceExist(other)) { + return false; + } + return this.color() != other.color(); + } + + @Override + public Color color() { + return color; + } + + @Override + public final Type type() { + return Type.PAWN; + } +} diff --git a/src/main/java/domain/piece/pawn/WhitePawn.java b/src/main/java/domain/piece/pawn/WhitePawn.java new file mode 100644 index 00000000000..9f92d4aea88 --- /dev/null +++ b/src/main/java/domain/piece/pawn/WhitePawn.java @@ -0,0 +1,30 @@ +package domain.piece.pawn; + +import domain.piece.Color; +import domain.position.Position; +import domain.position.Rank; + +public class WhitePawn extends PawnPiece { + private static final Rank INITIAL_RANK = Rank.TWO; + + public WhitePawn() { + super(Color.WHITE); + } + + @Override + protected void validateForwardMovement(final Position source, final Position target) { + if (!source.isLowerRankThan(target)) { + throw new IllegalArgumentException("폰은 앞으로 이동해야 합니다."); + } + } + + @Override + protected boolean isAtSameRank(final Position source) { + return source.isAtSameRank(INITIAL_RANK); + } + + @Override + public Color color() { + return Color.WHITE; + } +} diff --git a/src/main/java/domain/position/File.java b/src/main/java/domain/position/File.java new file mode 100644 index 00000000000..73d9f86cbc4 --- /dev/null +++ b/src/main/java/domain/position/File.java @@ -0,0 +1,66 @@ +package domain.position; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static java.lang.Math.max; +import static java.lang.Math.min; + +public enum File { + A("a", 0), + B("b", 1), + C("c", 2), + D("d", 3), + E("e", 4), + F("f", 5), + G("g", 6), + H("h", 7); + + private final String name; + private final int order; + + File(String name, int order) { + this.name = name; + this.order = order; + } + + public static File fromName(final String name) { + return Arrays.stream(values()) + .filter(file -> file.name.equals(name)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("존재하지 않은 file입니다.")); + } + + public static File fromOrder(final int order) { + return Arrays.stream(values()) + .filter(file -> file.order == order) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("존재하지 않은 file입니다.")); + } + + public List between(final File file) { + final List files = IntStream.range(min(this.order, file.order), max(this.order, file.order)) + .skip(1) + .mapToObj(File::fromOrder) + .collect(Collectors.toList()); + if (this.isLaterThan(file)) { + Collections.reverse(files); + } + return files; + } + + private boolean isLaterThan(final File file) { + return this.order > file.order; + } + + int subtract(final File file) { + return this.order - file.order; + } + + public int order() { + return order; + } +} diff --git a/src/main/java/domain/position/Position.java b/src/main/java/domain/position/Position.java new file mode 100644 index 00000000000..ff3bae8458f --- /dev/null +++ b/src/main/java/domain/position/Position.java @@ -0,0 +1,102 @@ +package domain.position; + +import java.util.Objects; + +public class Position { + private final File file; + private final Rank rank; + + public Position(final File file, final Rank rank) { + this.file = file; + this.rank = rank; + } + + public Position(final String file, final int rank) { + this(File.fromName(file), Rank.fromNumber(rank)); + } + + public boolean isStraightAt(final Position target) { + validateSamePosition(target); + return calculateFileGap(target) == 0 || calculateRankGap(target) == 0; + } + + public boolean isDiagonalAt(final Position target) { + validateSamePosition(target); + return calculateFileGap(target) == calculateRankGap(target); + } + + public boolean isKnightPositionAt(final Position target) { + validateSamePosition(target); + return calculateRankGap(target) * calculateFileGap(target) == 2; + } + + public boolean isAdjacentAt(final Position target) { + validateSamePosition(target); + return Math.max(calculateRankGap(target), calculateFileGap(target)) == 1; + } + + public boolean isDistanceAt(final Position target, final int distance) { + return calculateRankGap(target) + calculateFileGap(target) == distance; + } + + private void validateSamePosition(final Position target) { + if (this.equals(target)) { + throw new IllegalArgumentException("동일한 위치입니다."); + } + } + + public boolean isUpperRankThan(final Position target) { + return this.rank.isUpperThan(target.rank); + } + + public boolean isLowerRankThan(final Position target) { + return this.rank.isLowerThan(target.rank); + } + + public boolean isAtSameRank(final Rank rank) { + return this.rank.isSame(rank); + } + + boolean isVertical(final Position target) { + validateSamePosition(target); + return calculateFileGap(target) == 0 && calculateRankGap(target) > 0; + } + + boolean isHorizontal(final Position target) { + validateSamePosition(target); + return calculateFileGap(target) > 0 && calculateRankGap(target) == 0; + } + + int calculateRankGap(final Position target) { + return Math.abs(rank.subtract(target.rank)); + } + + int calculateFileGap(final Position target) { + return Math.abs(file.subtract(target.file)); + } + + public Rank rank() { + return rank; + } + + public File file() { + return file; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Position position = (Position) o; + return file == position.file && rank == position.rank; + } + + @Override + public int hashCode() { + return Objects.hash(file, rank); + } +} diff --git a/src/main/java/domain/position/Rank.java b/src/main/java/domain/position/Rank.java new file mode 100644 index 00000000000..d8f82bf61c8 --- /dev/null +++ b/src/main/java/domain/position/Rank.java @@ -0,0 +1,58 @@ +package domain.position; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public enum Rank { + EIGHT(8), + SEVEN(7), + SIX(6), + FIVE(5), + FOUR(4), + THREE(3), + TWO(2), + ONE(1); + + private final int number; + + Rank(int number) { + this.number = number; + } + + public static Rank fromNumber(final int number) { + return Arrays.stream(values()) + .filter(rank -> rank.number == number) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("존재하지 않은 rank입니다.")); + } + + public List between(final Rank target) { + final List ranks = IntStream.range(Math.min(this.number, target.number), Math.max(this.number, target.number)) + .skip(1) + .mapToObj(Rank::fromNumber) + .collect(Collectors.toList()); + if (this.isUpperThan(target)) { + Collections.reverse(ranks); + } + return ranks; + } + + boolean isUpperThan(final Rank rank) { + return this.number > rank.number; + } + + boolean isLowerThan(final Rank rank) { + return this.number < rank.number; + } + + boolean isSame(final Rank rank) { + return this.number == rank.number; + } + + int subtract(final Rank rank) { + return this.number - rank.number; + } +} diff --git a/src/main/java/domain/position/Route.java b/src/main/java/domain/position/Route.java new file mode 100644 index 00000000000..6c2a3006ca1 --- /dev/null +++ b/src/main/java/domain/position/Route.java @@ -0,0 +1,66 @@ +package domain.position; + +import domain.piece.Piece; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class Route { + private final List positions; + + private Route(final List positions) { + this.positions = positions; + } + + public static Route create(final Position source, final Position target) { + if (source.isKnightPositionAt(target) || source.isAdjacentAt(target)) { + return createEmptyRoute(); + } + if (source.isDiagonalAt(target)) { + return createDiagonalRoute(source, target); + } + if (source.isVertical(target)) { + return createVerticalRoute(source, target); + } + if (source.isHorizontal(target)) { + return createHorizontalRoute(source, target); + } + throw new IllegalArgumentException("잘못된 방향으로 이동하고 있습니다."); + } + + private static Route createEmptyRoute() { + return new Route(List.of()); + } + + private static Route createDiagonalRoute(final Position source, final Position target) { + final List files = source.file().between(target.file()); + final List ranks = source.rank().between(target.rank()); + return IntStream.range(0, files.size()) + .mapToObj(i -> new Position(files.get(i), ranks.get(i))) + .collect(Collectors.collectingAndThen(Collectors.toList(), Route::new)); + } + + private static Route createHorizontalRoute(final Position source, final Position target) { + final List files = source.file().between(target.file()); + return files.stream() + .map(file -> new Position(file, source.rank())) + .collect(Collectors.collectingAndThen(Collectors.toList(), Route::new)); + } + + private static Route createVerticalRoute(final Position source, final Position target) { + final List ranks = source.rank().between(target.rank()); + return ranks.stream() + .map(rank -> new Position(source.file(), rank)) + .collect(Collectors.collectingAndThen(Collectors.toList(), Route::new)); + } + + public boolean isBlocked(final Map board) { + return positions.stream().anyMatch(board::containsKey); + } + + List getRoute() { + return positions; + } +} diff --git a/src/main/java/view/Command.java b/src/main/java/view/Command.java new file mode 100644 index 00000000000..8336742975f --- /dev/null +++ b/src/main/java/view/Command.java @@ -0,0 +1,17 @@ +package view; + +public enum Command { + START("start"), + END("end"), + MOVE("move"); + + private final String message; + + Command(String message) { + this.message = message; + } + + public String message() { + return message; + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 00000000000..b975fdd5022 --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,53 @@ +package view; + +import controller.command.Command; +import controller.command.EndOnCommand; +import controller.command.MoveOnCommand; +import controller.command.StartOnCommand; +import domain.position.Position; + +import java.util.Scanner; + +public class InputView { + private final Scanner scanner; + + public InputView() { + this.scanner = new Scanner(System.in); + } + + public Command readStartCommand() { + String[] rawInput = scanner.nextLine().trim().split(" "); + if (hasSize(rawInput, 1) && "start".equals(rawInput[0])) { + return new StartOnCommand(); + } + throw new IllegalArgumentException("먼저, 게임을 시작해 주세요."); + } + + public Command readCommand() { + String[] rawInput = scanner.nextLine().trim().split(" "); + if (hasSize(rawInput, 1) && "start".equals(rawInput[0])) { + return new StartOnCommand(); + } + if (hasSize(rawInput, 3) && "move".equals(rawInput[0])) { + return new MoveOnCommand(resolvePosition(rawInput[1]), resolvePosition(rawInput[2])); + } + if (hasSize(rawInput, 1) && "end".equals(rawInput[0])) { + return new EndOnCommand(); + } + throw new IllegalArgumentException("잘못된 형식의 명령어입니다."); + } + + private Position resolvePosition(String position) { + String file = position.substring(0, 1); + String rank = position.substring(1); + try { + return new Position(file, Integer.parseInt(rank)); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("잘못된 형식의 명령어입니다."); + } + } + + private boolean hasSize(final String[] rawInput, int size) { + return rawInput.length == size; + } +} diff --git a/src/main/java/view/MessageResolver.java b/src/main/java/view/MessageResolver.java new file mode 100644 index 00000000000..6db19f02dcd --- /dev/null +++ b/src/main/java/view/MessageResolver.java @@ -0,0 +1,80 @@ +package view; + +import domain.board.ChessBoard; +import domain.piece.Piece; +import domain.piece.Type; +import domain.position.File; +import domain.position.Position; +import domain.position.Rank; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static view.Command.END; +import static view.Command.MOVE; +import static view.Command.START; + +public class MessageResolver { + public static final int BOARD_LENGTH = 8; + private static final String LINE_SEPARATOR = System.lineSeparator(); + private static final Map PIECE_DISPLAY = Map.of( + Type.PAWN, "p", + Type.KNIGHT, "n", + Type.BISHOP, "b", + Type.ROOK, "r", + Type.QUEEN, "q", + Type.KING, "k" + ); + + public String resolveGameStartMessage() { + String gameStartMessage = "> 체스 게임을 시작합니다."; + String gameStartCommandMessage = String.format("> 게임 시작 : %s", START.message()); + String gameEndCommandMessage = String.format("> 게임 종료 : %s", END.message()); + String gameMoveCommandMessage = String.format("> 게임 이동 : %s source위치 target위치 - 예. %s b2 b3", + MOVE.message(), MOVE.message()); + return String.join(LINE_SEPARATOR, gameStartMessage, gameStartCommandMessage, + gameEndCommandMessage, gameMoveCommandMessage); + } + + public String resolveBoard(ChessBoard board) { + List boardMessage = IntStream.rangeClosed(1, 8) + .mapToObj(rank -> resolveOneRank(board, Rank.fromNumber(rank))) + .collect(Collectors.toList()); + Collections.reverse(boardMessage); + return String.join(LINE_SEPARATOR, boardMessage); + } + + private String resolveOneRank(ChessBoard board, Rank targetRank) { + StringBuilder rankMessage = new StringBuilder(".".repeat(BOARD_LENGTH)); + board.getBoard().entrySet().stream() + .filter(entry -> resolvePosition(entry).rank() == targetRank) + .forEach(positionPieceEntry -> updateRankMessage(rankMessage, positionPieceEntry)); + return rankMessage.toString(); + } + + private void updateRankMessage(final StringBuilder rankMessage, final Map.Entry positionPieceEntry) { + Position position = resolvePosition(positionPieceEntry); + Piece piece = resolvePiece(positionPieceEntry); + File file = position.file(); + rankMessage.setCharAt(file.order(), pieceDisplay(piece).charAt(0)); + } + + private Piece resolvePiece(final Map.Entry positionAndPiece) { + return positionAndPiece.getValue(); + } + + private Position resolvePosition(final Map.Entry positionAndPiece) { + return positionAndPiece.getKey(); + } + + private String pieceDisplay(Piece piece) { + String pieceName = PIECE_DISPLAY.get(piece.type()); + if (piece.color().isBlack()) { + return pieceName.toUpperCase(); + } + return pieceName; + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 00000000000..02b389052b3 --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,24 @@ +package view; + +import domain.board.ChessBoard; + +public class OutputView { + private final MessageResolver messageResolver; + + public OutputView(final MessageResolver messageResolver) { + this.messageResolver = messageResolver; + } + + public void printGameGuideMessage() { + System.out.println(messageResolver.resolveGameStartMessage()); + } + + public void printBoard(ChessBoard board) { + String boardRankMessage = messageResolver.resolveBoard(board); + System.out.println(boardRankMessage); + } + + public void printErrorMessage(final String errorMessage) { + System.out.println(errorMessage); + } +} diff --git a/src/test/java/domain/board/ChessBoardTest.java b/src/test/java/domain/board/ChessBoardTest.java new file mode 100644 index 00000000000..73b565c6b1f --- /dev/null +++ b/src/test/java/domain/board/ChessBoardTest.java @@ -0,0 +1,120 @@ +package domain.board; + +import domain.piece.Color; +import domain.piece.Piece; +import domain.piece.nonpawn.Queen; +import domain.piece.pawn.BlackPawn; +import domain.piece.pawn.WhitePawn; +import domain.position.File; +import domain.position.Position; +import domain.position.Rank; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class ChessBoardTest { + @Test + void 출발_위치에_기물_존재하지_않으면_예외가_발생한다() { + Position source = new Position(File.F, Rank.FOUR); + Position target = new Position(File.F, Rank.EIGHT); + ChessBoard board = new ChessBoard(Map.of()); + + assertThatThrownBy(() -> board.move(source, target)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("피스가 없습니다."); + } + + @Test + void 기물을_움직일_때_중간에_다른_기물이_있으면_예외가_발생한다() { + Position source = new Position(File.F, Rank.FOUR); + Position target = new Position(File.F, Rank.EIGHT); + Position between = new Position(File.F, Rank.FIVE); + ChessBoard board = new ChessBoard(Map.of( + source, new Queen(Color.WHITE), + between, new BlackPawn() + )); + + assertThatThrownBy(() -> board.move(source, target)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("중간에 말이 있어서 이동할 수 없습니다."); + } + + @Test + void 기물을_움직일_때_중간에_다른_기물이_없으면_이동한다() { + Piece piece = new Queen(Color.WHITE); + Position source = new Position(File.F, Rank.FOUR); + Position target = new Position(File.F, Rank.EIGHT); + ChessBoard board = new ChessBoard(Map.of(source, piece)); + + board.move(source, target); + assertThat(board.getBoard()) + .containsEntry(target, piece) + .doesNotContainKey(source); + } + + @Test + void 기물을_잡는다() { + Piece piece = new WhitePawn(); + Position source = new Position(File.F, Rank.FOUR); + Position target = new Position(File.G, Rank.FIVE); + ChessBoard board = new ChessBoard(Map.of( + source, piece, + target, new BlackPawn()) + ); + + board.move(source, target); + assertThat(board.getBoard()) + .containsEntry(target, piece) + .doesNotContainKey(source); + } + + @Test + void 게임을_시작하고_피스를_한_번_움직이면_다음은_BLACK_턴이다() { + Position resource = new Position(File.F, Rank.FOUR); + Position target = new Position(File.F, Rank.EIGHT); + ChessBoard board = new ChessBoard(Map.of(resource, new Queen(Color.WHITE))); + board.move(resource, target); + + assertThatThrownBy(() -> board.move(target, resource)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("상대 턴입니다."); + } + + @Test + void 피스가_움직이지_않으면_턴이_바뀌지_않는다() { + Position resource = new Position(File.F, Rank.FOUR); + Position target = new Position(File.F, Rank.EIGHT); + Position between = new Position(File.F, Rank.FIVE); + ChessBoard board = new ChessBoard(Map.of( + resource, new Queen(Color.WHITE), + between, new BlackPawn() + )); + + assertThatThrownBy(() -> board.move(resource, target)) + .isInstanceOf(IllegalArgumentException.class); + assertThatCode(() -> board.move(resource, between)) + .doesNotThrowAnyException(); + } + + @Test + void 피스를_두_번_움직이면_턴이_되돌아온다() { + Position whiteResource = new Position(File.F, Rank.FOUR); + Position whiteTarget = new Position(File.F, Rank.EIGHT); + Position blackResource = new Position(File.A, Rank.FOUR); + Position blackTarget = new Position(File.A, Rank.EIGHT); + ChessBoard board = new ChessBoard(Map.of( + whiteResource, new Queen(Color.WHITE), + blackResource, new Queen(Color.BLACK) + )); + + board.move(whiteResource, whiteTarget); + board.move(blackResource, blackTarget); + + assertThatCode(() -> board.move(whiteTarget, whiteResource)) + .doesNotThrowAnyException(); + } +} diff --git a/src/test/java/domain/board/TurnTest.java b/src/test/java/domain/board/TurnTest.java new file mode 100644 index 00000000000..da743c9dec8 --- /dev/null +++ b/src/test/java/domain/board/TurnTest.java @@ -0,0 +1,45 @@ +package domain.board; + +import domain.piece.Color; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class TurnTest { + @Test + void 첫_턴은_WHITE이다() { + Turn turn = new Turn(); + + assertThat(turn.isOpponentTurn(Color.BLACK)).isTrue(); + } + + @Test + void 턴이_1번_정상적으로_변경된다() { + Turn turn = new Turn(); + + turn.flip(); + + assertThat(turn.isOpponentTurn(Color.WHITE)).isTrue(); + } + + @Test + void 턴이_2번_정상적으로_변경된다() { + Turn turn = new Turn(); + + turn.flip(); + turn.flip(); + + assertThat(turn.isOpponentTurn(Color.BLACK)).isTrue(); + } + + @Test + void 턴이_3번_정상적으로_변경된다() { + Turn turn = new Turn(); + + turn.flip(); + turn.flip(); + turn.flip(); + + assertThat(turn.isOpponentTurn(Color.WHITE)).isTrue(); + } +} diff --git a/src/test/java/domain/piece/nonpawn/BishopTest.java b/src/test/java/domain/piece/nonpawn/BishopTest.java new file mode 100644 index 00000000000..7e6f9c09f07 --- /dev/null +++ b/src/test/java/domain/piece/nonpawn/BishopTest.java @@ -0,0 +1,92 @@ +package domain.piece.nonpawn; + +import domain.piece.Color; +import domain.piece.Piece; +import domain.piece.pawn.BlackPawn; +import domain.piece.pawn.WhitePawn; +import domain.position.File; +import domain.position.Position; +import domain.position.Rank; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class BishopTest { + private final Piece bishop = new Bishop(Color.WHITE); + + @Test + void 대각선_방향으로_이동할_수_있다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.G, Rank.SEVEN); + Piece other = new BlackPawn(); + + assertThatCode(() -> bishop.validateMovement(source, target, other)) + .doesNotThrowAnyException(); + } + + @Test + void 직선_방향으로_이동하면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.D, Rank.EIGHT); + Piece other = new BlackPawn(); + + assertThatThrownBy(() -> bishop.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("비숍은 대각선 방향으로만 이동할 수 있습니다."); + } + + @Test + void L자_방향으로_이동하면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.F, Rank.THREE); + Piece other = new BlackPawn(); + + assertThatThrownBy(() -> bishop.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("비숍은 대각선 방향으로만 이동할 수 있습니다."); + } + + @Test + void 정의되지_않은_방향으로_이동하면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.A, Rank.TWO); + Piece other = new BlackPawn(); + + assertThatThrownBy(() -> bishop.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("비숍은 대각선 방향으로만 이동할 수 있습니다."); + } + + @Test + void 거리에_상관없이_이동할_수_있다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.H, Rank.EIGHT); + Piece other = new BlackPawn(); + + assertThatCode(() -> bishop.validateMovement(source, target, other)) + .doesNotThrowAnyException(); + } + + @Test + void 이동하지_않으면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.D, Rank.FOUR); + Piece other = new BlackPawn(); + + assertThatThrownBy(() -> bishop.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("동일한 위치입니다."); + } + + @Test + void 같은_팀의_말을_잡으면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.E, Rank.FIVE); + Piece other = new WhitePawn(); + + assertThatThrownBy(() -> bishop.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("같은 팀의 말을 잡을 수 없습니다."); + } +} diff --git a/src/test/java/domain/piece/nonpawn/KingTest.java b/src/test/java/domain/piece/nonpawn/KingTest.java new file mode 100644 index 00000000000..2a3fafa4f1c --- /dev/null +++ b/src/test/java/domain/piece/nonpawn/KingTest.java @@ -0,0 +1,60 @@ +package domain.piece.nonpawn; + +import domain.piece.Color; +import domain.piece.Piece; +import domain.piece.pawn.BlackPawn; +import domain.piece.pawn.WhitePawn; +import domain.position.File; +import domain.position.Position; +import domain.position.Rank; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class KingTest { + private final Piece king = new King(Color.WHITE); + + @Test + void 한_칸만_이동할_수_있다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.E, Rank.FIVE); + Piece other = new BlackPawn(); + + assertThatCode(() -> king.validateMovement(source, target, other)) + .doesNotThrowAnyException(); + } + + @Test + void 한_칸_이상_이동하면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.F, Rank.FOUR); + Piece other = new BlackPawn(); + + assertThatThrownBy(() -> king.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("킹은 한 번에 1칸만 이동할 수 있습니다"); + } + + @Test + void 이동하지_않으면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.D, Rank.FOUR); + Piece other = new BlackPawn(); + + assertThatThrownBy(() -> king.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("동일한 위치입니다."); + } + + @Test + void 같은_팀의_말을_잡으면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.E, Rank.FIVE); + Piece other = new WhitePawn(); + + assertThatThrownBy(() -> king.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("같은 팀의 말을 잡을 수 없습니다."); + } +} diff --git a/src/test/java/domain/piece/nonpawn/KnightTest.java b/src/test/java/domain/piece/nonpawn/KnightTest.java new file mode 100644 index 00000000000..23a1cbfaa14 --- /dev/null +++ b/src/test/java/domain/piece/nonpawn/KnightTest.java @@ -0,0 +1,82 @@ +package domain.piece.nonpawn; + +import domain.piece.Color; +import domain.piece.Piece; +import domain.piece.pawn.BlackPawn; +import domain.piece.pawn.WhitePawn; +import domain.position.File; +import domain.position.Position; +import domain.position.Rank; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class KnightTest { + private final Piece knight = new Knight(Color.WHITE); + + @Test + void L자_방향으로_이동할_수_있다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.F, Rank.THREE); + Piece other = new BlackPawn(); + + assertThatCode(() -> knight.validateMovement(source, target, other)) + .doesNotThrowAnyException(); + } + + @Test + void 대각선_방향으로_이동하면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.G, Rank.SEVEN); + Piece other = new BlackPawn(); + + assertThatThrownBy(() -> knight.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("나이트는 L자 방향으로만 이동할 수 있습니다."); + } + + @Test + void 직선_방향으로_이동하면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.D, Rank.EIGHT); + Piece other = new BlackPawn(); + + assertThatThrownBy(() -> knight.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("나이트는 L자 방향으로만 이동할 수 있습니다."); + } + + @Test + void 정의되지_않은_방향으로_이동하면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.A, Rank.TWO); + Piece other = new BlackPawn(); + + assertThatThrownBy(() -> knight.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("나이트는 L자 방향으로만 이동할 수 있습니다."); + } + + @Test + void 이동하지_않으면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.D, Rank.FOUR); + Piece other = new BlackPawn(); + + assertThatThrownBy(() -> knight.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("동일한 위치입니다."); + } + + @Test + void 같은_팀의_말을_잡으면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.E, Rank.FIVE); + Piece other = new WhitePawn(); + + assertThatThrownBy(() -> knight.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("같은 팀의 말을 잡을 수 없습니다."); + } +} diff --git a/src/test/java/domain/piece/nonpawn/QueenTest.java b/src/test/java/domain/piece/nonpawn/QueenTest.java new file mode 100644 index 00000000000..8f78deac82a --- /dev/null +++ b/src/test/java/domain/piece/nonpawn/QueenTest.java @@ -0,0 +1,92 @@ +package domain.piece.nonpawn; + +import domain.piece.Color; +import domain.piece.Piece; +import domain.piece.pawn.BlackPawn; +import domain.piece.pawn.WhitePawn; +import domain.position.File; +import domain.position.Position; +import domain.position.Rank; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class QueenTest { + private final Piece queen = new Queen(Color.WHITE); + + @Test + void 직선_방향으로_이동할_수_있다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.D, Rank.EIGHT); + Piece other = new BlackPawn(); + + assertThatCode(() -> queen.validateMovement(source, target, other)) + .doesNotThrowAnyException(); + } + + @Test + void 대각선_방향으로_이동할_수_있다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.G, Rank.SEVEN); + Piece other = new BlackPawn(); + + assertThatCode(() -> queen.validateMovement(source, target, other)) + .doesNotThrowAnyException(); + + } + + @Test + void L자_방향으로_이동하면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.F, Rank.THREE); + Piece other = new BlackPawn(); + + assertThatThrownBy(() -> queen.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("은 대각선, 수평, 수직 방향으로만 이동할 수 있습니다."); + } + + @Test + void 정의되지_않은_방향으로_이동하면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.A, Rank.TWO); + Piece other = new BlackPawn(); + + assertThatThrownBy(() -> queen.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("퀸은 대각선, 수평, 수직 방향으로만 이동할 수 있습니다."); + } + + @Test + void 거리에_상관없이_이동할_수_있다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.D, Rank.EIGHT); + Piece other = new BlackPawn(); + + assertThatCode(() -> queen.validateMovement(source, target, other)) + .doesNotThrowAnyException(); + } + + @Test + void 이동하지_않으면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.D, Rank.FOUR); + Piece other = new BlackPawn(); + + assertThatThrownBy(() -> queen.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("동일한 위치입니다."); + } + + @Test + void 같은_팀의_말을_잡으면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.E, Rank.FIVE); + Piece other = new WhitePawn(); + + assertThatThrownBy(() -> queen.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("같은 팀의 말을 잡을 수 없습니다."); + } +} diff --git a/src/test/java/domain/piece/nonpawn/RookTest.java b/src/test/java/domain/piece/nonpawn/RookTest.java new file mode 100644 index 00000000000..48eb6a36767 --- /dev/null +++ b/src/test/java/domain/piece/nonpawn/RookTest.java @@ -0,0 +1,102 @@ +package domain.piece.nonpawn; + +import domain.piece.Color; +import domain.piece.Piece; +import domain.piece.pawn.BlackPawn; +import domain.piece.pawn.WhitePawn; +import domain.position.File; +import domain.position.Position; +import domain.position.Rank; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class RookTest { + private final Piece rook = new Rook(Color.WHITE); + + @Test + void 수평_방향으로_이동할_수_있다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.D, Rank.EIGHT); + Piece other = new BlackPawn(); + + assertThatCode(() -> rook.validateMovement(source, target, other)) + .doesNotThrowAnyException(); + } + + @Test + void 수직_방향으로_이동할_수_있다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.A, Rank.FOUR); + Piece other = new BlackPawn(); + + assertThatCode(() -> rook.validateMovement(source, target, other)) + .doesNotThrowAnyException(); + } + + @Test + void 대각선_방향으로_이동하면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.G, Rank.SEVEN); + Piece other = new BlackPawn(); + + assertThatThrownBy(() -> rook.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("룩은 수평, 수직 방향으로만 이동할 수 있습니다."); + } + + @Test + void L자_방향으로_이동하면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.F, Rank.THREE); + Piece other = new BlackPawn(); + + assertThatThrownBy(() -> rook.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("은 수평, 수직 방향으로만 이동할 수 있습니다."); + } + + @Test + void 정의되지_않은_방향으로_이동하면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.A, Rank.TWO); + Piece other = new BlackPawn(); + + assertThatThrownBy(() -> rook.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("은 수평, 수직 방향으로만 이동할 수 있습니다."); + } + + @Test + void 거리에_상관없이_이동할_수_있다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.D, Rank.EIGHT); + Piece other = new BlackPawn(); + + assertThatCode(() -> rook.validateMovement(source, target, other)) + .doesNotThrowAnyException(); + } + + @Test + void 이동하지_않으면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.D, Rank.FOUR); + Piece other = new BlackPawn(); + + assertThatThrownBy(() -> rook.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("동일한 위치입니다."); + } + + @Test + void 같은_팀의_말을_잡으면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.E, Rank.FIVE); + Piece other = new WhitePawn(); + + assertThatThrownBy(() -> rook.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("같은 팀의 말을 잡을 수 없습니다."); + } +} diff --git a/src/test/java/domain/piece/pawn/BlackPawnTest.java b/src/test/java/domain/piece/pawn/BlackPawnTest.java new file mode 100644 index 00000000000..a016a0234ca --- /dev/null +++ b/src/test/java/domain/piece/pawn/BlackPawnTest.java @@ -0,0 +1,133 @@ +package domain.piece.pawn; + +import domain.piece.Empty; +import domain.piece.Piece; +import domain.position.File; +import domain.position.Position; +import domain.position.Rank; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class BlackPawnTest { + private final Piece blackPawn = new BlackPawn(); + + @Test + void 직선_방향으로_한_칸_이동할_수_있다() { + Position source = new Position(File.D, Rank.FIVE); + Position target = new Position(File.D, Rank.FOUR); + Piece other = Empty.getInstance(); + + assertThatCode(() -> blackPawn.validateMovement(source, target, other)) + .doesNotThrowAnyException(); + } + + @Test + void 앞이_빈_공간이_아니면_직선_방향으로_이동할_수_없다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.D, Rank.THREE); + Piece other = new WhitePawn(); + + assertThatThrownBy(() -> blackPawn.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("잘못된 방향으로 이동하고 있습니다."); + } + + @Test + void 초기_위치_일_때_직선_방향으로_두_칸_이동할_수_있다() { + Position source = new Position(File.D, Rank.SEVEN); + Position target = new Position(File.D, Rank.FIVE); + Piece other = Empty.getInstance(); + + assertThatCode(() -> blackPawn.validateMovement(source, target, other)) + .doesNotThrowAnyException(); + } + + @Test + void 초기_위치가_아닐_때_직선_방향으로_두_칸_이동하면_예외가_발생한다() { + Position source = new Position(File.D, Rank.SIX); + Position target = new Position(File.D, Rank.FOUR); + Piece other = Empty.getInstance(); + + assertThatThrownBy(() -> blackPawn.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("잘못된 방향으로 이동하고 있습니다."); + } + + @Test + void 대각선_방향에_적이_있으면_이동할_수_있다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.E, Rank.THREE); + Piece other = new WhitePawn(); + + assertThatCode(() -> blackPawn.validateMovement(source, target, other)) + .doesNotThrowAnyException(); + } + + @Test + void 대각선_방향에_적이_없을_때_이동할_경우_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.E, Rank.THREE); + Piece other = Empty.getInstance(); + + assertThatThrownBy(() -> blackPawn.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("잘못된 방향으로 이동하고 있습니다."); + } + + @Test + void 대각선_방향으로_두_칸_이동할_경우_예외가_발생한다() { + Position source = new Position(File.D, Rank.FIVE); + Position target = new Position(File.F, Rank.THREE); + Piece other = new WhitePawn(); + + assertThatThrownBy(() -> blackPawn.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("잘못된 방향으로 이동하고 있습니다."); + } + + @Test + void 뒤로_이동하려고_하면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.D, Rank.FIVE); + Piece other = Empty.getInstance(); + + assertThatThrownBy(() -> blackPawn.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("폰은 앞으로 이동해야 합니다."); + } + + @Test + void L자_방향으로_이동하면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FIVE); + Position target = new Position(File.B, Rank.FOUR); + Piece other = Empty.getInstance(); + + assertThatThrownBy(() -> blackPawn.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("잘못된 방향으로 이동하고 있습니다."); + } + + @Test + void 정의되지_않은_방향으로_이동하면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FIVE); + Position target = new Position(File.G, Rank.ONE); + Piece other = Empty.getInstance(); + + assertThatThrownBy(() -> blackPawn.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("잘못된 방향으로 이동하고 있습니다."); + } + + @Test + void 같은_팀의_말을_잡으면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.E, Rank.THREE); + Piece other = new BlackPawn(); + + assertThatThrownBy(() -> blackPawn.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("같은 팀의 말을 잡을 수 없습니다."); + } +} diff --git a/src/test/java/domain/piece/pawn/WhitePawnTest.java b/src/test/java/domain/piece/pawn/WhitePawnTest.java new file mode 100644 index 00000000000..c670eeb9f85 --- /dev/null +++ b/src/test/java/domain/piece/pawn/WhitePawnTest.java @@ -0,0 +1,133 @@ +package domain.piece.pawn; + +import domain.piece.Empty; +import domain.piece.Piece; +import domain.position.File; +import domain.position.Position; +import domain.position.Rank; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class WhitePawnTest { + private final Piece whitePawn = new WhitePawn(); + + @Test + void 직선_방향으로_한_칸_이동할_수_있다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.D, Rank.FIVE); + Piece other = Empty.getInstance(); + + assertThatCode(() -> whitePawn.validateMovement(source, target, other)) + .doesNotThrowAnyException(); + } + + @Test + void 앞이_빈_공간이_아니면_직선_방향으로_이동할_수_없다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.D, Rank.FIVE); + Piece other = new BlackPawn(); + + assertThatThrownBy(() -> whitePawn.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("잘못된 방향으로 이동하고 있습니다."); + } + + @Test + void 초기_위치_일_때_직선_방향으로_두_칸_이동할_수_있다() { + Position source = new Position(File.D, Rank.TWO); + Position target = new Position(File.D, Rank.FOUR); + Piece other = Empty.getInstance(); + + assertThatCode(() -> whitePawn.validateMovement(source, target, other)) + .doesNotThrowAnyException(); + } + + @Test + void 초기_위치가_아닐_때_직선_방향으로_두_칸_이동하면_예외가_발생한다() { + Position source = new Position(File.D, Rank.THREE); + Position target = new Position(File.D, Rank.FIVE); + Piece other = Empty.getInstance(); + + assertThatThrownBy(() -> whitePawn.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("잘못된 방향으로 이동하고 있습니다."); + } + + @Test + void 대각선_방향에_적이_있으면_이동할_수_있다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.E, Rank.FIVE); + Piece other = new BlackPawn(); + + assertThatCode(() -> whitePawn.validateMovement(source, target, other)) + .doesNotThrowAnyException(); + } + + @Test + void 대각선_방향에_적이_없을_때_이동할_경우_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.E, Rank.FIVE); + Piece other = Empty.getInstance(); + + assertThatThrownBy(() -> whitePawn.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("잘못된 방향으로 이동하고 있습니다."); + } + + @Test + void 대각선_방향으로_두_칸_이동할_경우_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.F, Rank.SIX); + Piece other = new BlackPawn(); + + assertThatThrownBy(() -> whitePawn.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("잘못된 방향으로 이동하고 있습니다."); + } + + @Test + void 뒤로_이동하려고_하면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.D, Rank.THREE); + Piece other = Empty.getInstance(); + + assertThatThrownBy(() -> whitePawn.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("폰은 앞으로 이동해야 합니다."); + } + + @Test + void L자_방향으로_이동하면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.F, Rank.FIVE); + Piece other = Empty.getInstance(); + + assertThatThrownBy(() -> whitePawn.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("잘못된 방향으로 이동하고 있습니다."); + } + + @Test + void 정의되지_않은_방향으로_이동하면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.A, Rank.EIGHT); + Piece other = Empty.getInstance(); + + assertThatThrownBy(() -> whitePawn.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("잘못된 방향으로 이동하고 있습니다."); + } + + @Test + void 같은_팀의_말을_잡으면_예외가_발생한다() { + Position source = new Position(File.D, Rank.FOUR); + Position target = new Position(File.E, Rank.FIVE); + Piece other = new WhitePawn(); + + assertThatThrownBy(() -> whitePawn.validateMovement(source, target, other)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("같은 팀의 말을 잡을 수 없습니다."); + } +} diff --git a/src/test/java/domain/position/FileTest.java b/src/test/java/domain/position/FileTest.java new file mode 100644 index 00000000000..4df3a3a6d6e --- /dev/null +++ b/src/test/java/domain/position/FileTest.java @@ -0,0 +1,41 @@ +package domain.position; + +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; + +class FileTest { + @Test + void 존재하지_않은_file명을_찾을_경우_예외가_발생한다() { + assertThatThrownBy(() -> File.fromName("i")) + .isExactlyInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("존재하지 않은 file입니다."); + } + + @Test + void A와_F_사이에_존재하는_file_목록을_반환한다() { + File source = File.A; + File target = File.F; + + List betweenFiles = source.between(target); + + assertThat(betweenFiles).containsExactlyElementsOf(List.of( + File.B, File.C, File.D, File.E + )); + } + + @Test + void F와_A_사이에_존재하는_file_목록을_반환한다() { + File source = File.F; + File target = File.A; + + List betweenFiles = source.between(target); + + assertThat(betweenFiles).containsExactlyElementsOf(List.of( + File.E, File.D, File.C, File.B + )); + } +} diff --git a/src/test/java/domain/position/PositionTest.java b/src/test/java/domain/position/PositionTest.java new file mode 100644 index 00000000000..1391a1c935c --- /dev/null +++ b/src/test/java/domain/position/PositionTest.java @@ -0,0 +1,4 @@ +package domain.position; + +class PositionTest { +} diff --git a/src/test/java/domain/position/RankTest.java b/src/test/java/domain/position/RankTest.java new file mode 100644 index 00000000000..e535f626c11 --- /dev/null +++ b/src/test/java/domain/position/RankTest.java @@ -0,0 +1,48 @@ +package domain.position; + +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; + +class RankTest { + @Test + void 존재하지_않은_rank를_찾을_경우_예외가_발생한다() { + assertThatThrownBy(() -> Rank.fromNumber(0)) + .isExactlyInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("존재하지 않은 rank입니다."); + } + + @Test + void 존재하는_rank를_찾을_경우_해당_rank을_반환한다() { + Rank rank = Rank.fromNumber(1); + + assertThat(rank).isEqualTo(Rank.ONE); + } + + @Test + void ONE와_EIGHT_사이에_존재하는_rank_목록을_반환한다() { + Rank source = Rank.ONE; + Rank target = Rank.EIGHT; + + List betweenRanks = source.between(target); + + assertThat(betweenRanks).containsExactlyElementsOf(List.of( + Rank.TWO, Rank.THREE, Rank.FOUR, Rank.FIVE, Rank.SIX, Rank.SEVEN + )); + } + + @Test + void EIGHT와_ONE_사이에_존재하는_rank_목록을_반환한다() { + Rank source = Rank.EIGHT; + Rank target = Rank.ONE; + + List betweenRanks = source.between(target); + + assertThat(betweenRanks).containsExactlyElementsOf(List.of( + Rank.SEVEN, Rank.SIX, Rank.FIVE, Rank.FOUR, Rank.THREE, Rank.TWO + )); + } +} diff --git a/src/test/java/domain/position/RouteTest.java b/src/test/java/domain/position/RouteTest.java new file mode 100644 index 00000000000..f101bf449cd --- /dev/null +++ b/src/test/java/domain/position/RouteTest.java @@ -0,0 +1,255 @@ +package domain.position; + +import domain.piece.Piece; +import domain.piece.pawn.WhitePawn; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class RouteTest { + @Nested + class 경로_생성 { + @Test + void 인접한_UP_방향으로_이동하는_경로를_반환한다() { + Position source = new Position(File.F, Rank.FIVE); + Position target = new Position(File.F, Rank.SIX); + + Route route = Route.create(source, target); + assertThat(route.getRoute()).isEmpty(); + } + + @Test + void 인접한_LEFT_방향으로_이동하는_경로를_반환한다() { + Position source = new Position(File.F, Rank.FIVE); + Position target = new Position(File.E, Rank.FIVE); + + Route route = Route.create(source, target); + assertThat(route.getRoute()).isEmpty(); + } + + @Test + void UP_방향으로_이동하는_경로를_반환한다() { + Position source = new Position(File.F, Rank.FIVE); + Position target = new Position(File.F, Rank.EIGHT); + + Route route = Route.create(source, target); + assertThat(route.getRoute()) + .hasSize(2) + .containsExactlyInAnyOrderElementsOf(List.of( + new Position(File.F, Rank.SIX), + new Position(File.F, Rank.SEVEN) + )); + } + + @Test + void UP_RIGHT_방향으로_이동하는_경로를_반환한다() { + Position source = new Position(File.F, Rank.FIVE); + Position target = new Position(File.H, Rank.SEVEN); + + Route route = Route.create(source, target); + assertThat(route.getRoute()) + .hasSize(1) + .containsExactly(new Position(File.G, Rank.SIX)); + } + + @Test + void RIGHT_방향으로_이동하는_경로를_반환한다() { + Position source = new Position(File.F, Rank.FIVE); + Position target = new Position(File.G, Rank.FIVE); + + Route route = Route.create(source, target); + assertThat(route.getRoute()).isEmpty(); + } + + @Test + void DOWN_RIGHT_방향으로_이동하는_경로를_반환한다() { + Position source = new Position(File.F, Rank.FIVE); + Position target = new Position(File.H, Rank.THREE); + + Route route = Route.create(source, target); + assertThat(route.getRoute()) + .hasSize(1) + .containsExactly(new Position(File.G, Rank.FOUR)); + } + + @Test + void DOWN_방향으로_이동하는_경로를_반환한다() { + Position source = new Position(File.F, Rank.FIVE); + Position target = new Position(File.F, Rank.TWO); + + Route route = Route.create(source, target); + assertThat(route.getRoute()) + .hasSize(2) + .containsExactlyInAnyOrderElementsOf(List.of( + new Position(File.F, Rank.FOUR), + new Position(File.F, Rank.THREE) + )); + } + + @Test + void DOWN_LEFT_방향으로_이동하는_경로를_반환한다() { + Position source = new Position(File.F, Rank.FIVE); + Position target = new Position(File.C, Rank.TWO); + + Route route = Route.create(source, target); + assertThat(route.getRoute()) + .hasSize(2) + .containsExactlyInAnyOrderElementsOf(List.of( + new Position(File.E, Rank.FOUR), + new Position(File.D, Rank.THREE) + )); + } + + @Test + void LEFT_방향으로_이동하는_경로를_반환한다() { + Position source = new Position(File.F, Rank.FIVE); + Position target = new Position(File.C, Rank.FIVE); + + Route route = Route.create(source, target); + assertThat(route.getRoute()) + .hasSize(2) + .containsExactlyInAnyOrderElementsOf(List.of( + new Position(File.E, Rank.FIVE), + new Position(File.D, Rank.FIVE) + )); + } + + @Test + void UP_LEFT_방향으로_이동하는_경로를_반환한다() { + Position source = new Position(File.E, Rank.FOUR); + Position target = new Position(File.A, Rank.EIGHT); + + Route route = Route.create(source, target); + assertThat(route.getRoute()) + .hasSize(3) + .containsExactlyInAnyOrderElementsOf(List.of( + new Position(File.D, Rank.FIVE), + new Position(File.C, Rank.SIX), + new Position(File.B, Rank.SEVEN) + )); + } + + @Test + void UP_UP_LEFT_방향으로_이동하는_경로를_반환한다() { + Position source = new Position(File.E, Rank.FOUR); + Position target = new Position(File.D, Rank.SIX); + + Route route = Route.create(source, target); + assertThat(route.getRoute()).isEmpty(); + } + + @Test + void UP_UP_RIGHT_방향으로_이동하는_경로를_반환한다() { + Position source = new Position(File.E, Rank.FOUR); + Position target = new Position(File.F, Rank.SIX); + + Route route = Route.create(source, target); + assertThat(route.getRoute()).isEmpty(); + } + + @Test + void RIGHT_RIGHT_UP_방향으로_이동하는_경로를_반환한다() { + Position source = new Position(File.E, Rank.FOUR); + Position target = new Position(File.G, Rank.FIVE); + + Route route = Route.create(source, target); + assertThat(route.getRoute()).isEmpty(); + } + + @Test + void RIGHT_RIGHT_DOWN_방향으로_이동하는_경로를_반환한다() { + Position source = new Position(File.E, Rank.FOUR); + Position target = new Position(File.G, Rank.THREE); + + Route route = Route.create(source, target); + assertThat(route.getRoute()).isEmpty(); + } + + @Test + void DOWN_DOWN_RIGHT_방향으로_이동하는_경로를_반환한다() { + Position source = new Position(File.E, Rank.FOUR); + Position target = new Position(File.F, Rank.TWO); + + Route route = Route.create(source, target); + assertThat(route.getRoute()).isEmpty(); + } + + @Test + void DOWN_DOWN_LEFT_방향으로_이동하는_경로를_반환한다() { + Position source = new Position(File.E, Rank.FOUR); + Position target = new Position(File.D, Rank.TWO); + + Route route = Route.create(source, target); + assertThat(route.getRoute()).isEmpty(); + } + + @Test + void LEFT_LEFT_DOWN_방향으로_이동하는_경로를_반환한다() { + Position source = new Position(File.E, Rank.FOUR); + Position target = new Position(File.C, Rank.THREE); + + Route route = Route.create(source, target); + assertThat(route.getRoute()).isEmpty(); + } + + @Test + void LEFT_LEFT_UP_방향으로_이동하는_경로를_반환한다() { + Position source = new Position(File.E, Rank.FOUR); + Position target = new Position(File.C, Rank.FIVE); + + Route route = Route.create(source, target); + assertThat(route.getRoute()).isEmpty(); + } + + @Test + void LEFT_LEFT_LEFT_UP_방향으로_이동하면_예외가_발생한다() { + Position source = new Position(File.E, Rank.FOUR); + Position target = new Position(File.B, Rank.FIVE); + + assertThatThrownBy(() -> Route.create(source, target)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("잘못된 방향으로 이동하고 있습니다."); + } + } + + @Nested + class 경로_막힘 { + @Test + void 경로는_다른_피스가_없으면_막히지_않는다() { + Position source = new Position(File.F, Rank.FIVE); + Position target = new Position(File.F, Rank.SEVEN); + Route route = Route.create(source, target); + + Map emptyBoard = Map.of(); + + assertThat(route.isBlocked(emptyBoard)).isFalse(); + } + + @Test + void 도착_지점에_폰이_있어도_경로는_막히지_않는다() { + Position source = new Position(File.F, Rank.FIVE); + Position target = new Position(File.F, Rank.SIX); + Route route = Route.create(source, target); + + Map board = Map.of(target, new WhitePawn()); + + assertThat(route.isBlocked(board)).isFalse(); + } + + @Test + void 출발_지점과_도착_지점_사이에_폰이_있으면_경로가_막힌다() { + Position source = new Position(File.F, Rank.FIVE); + Position target = new Position(File.C, Rank.FIVE); + Route route = Route.create(source, target); + + Map board = Map.of(new Position(File.D, Rank.FIVE), new WhitePawn()); + + assertThat(route.isBlocked(board)).isTrue(); + } + } +} From 77cdad5f266c279a27a8ef18203952fce9c3def4 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sun, 24 Mar 2024 17:10:35 +0900 Subject: [PATCH 02/94] =?UTF-8?q?remove:=20=EB=88=84=EB=9D=BD=EB=90=9C=20T?= =?UTF-8?q?urn=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/board/Turn.java | 27 -------------- src/test/java/domain/board/TurnTest.java | 45 ------------------------ 2 files changed, 72 deletions(-) delete mode 100644 src/main/java/domain/board/Turn.java delete mode 100644 src/test/java/domain/board/TurnTest.java diff --git a/src/main/java/domain/board/Turn.java b/src/main/java/domain/board/Turn.java deleted file mode 100644 index 637ce166a34..00000000000 --- a/src/main/java/domain/board/Turn.java +++ /dev/null @@ -1,27 +0,0 @@ -package domain.board; - -import domain.piece.Color; - -public class Turn { - private Color color; - - private Turn(final Color color) { - this.color = color; - } - - Turn() { - this(Color.WHITE); - } - - void flip() { - if (this.color.isBlack()) { - this.color = Color.WHITE; - return; - } - this.color = Color.BLACK; - } - - boolean isOpponentTurn(final Color color) { - return this.color != color && !color.isNeutrality(); - } -} diff --git a/src/test/java/domain/board/TurnTest.java b/src/test/java/domain/board/TurnTest.java deleted file mode 100644 index da743c9dec8..00000000000 --- a/src/test/java/domain/board/TurnTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package domain.board; - -import domain.piece.Color; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -class TurnTest { - @Test - void 첫_턴은_WHITE이다() { - Turn turn = new Turn(); - - assertThat(turn.isOpponentTurn(Color.BLACK)).isTrue(); - } - - @Test - void 턴이_1번_정상적으로_변경된다() { - Turn turn = new Turn(); - - turn.flip(); - - assertThat(turn.isOpponentTurn(Color.WHITE)).isTrue(); - } - - @Test - void 턴이_2번_정상적으로_변경된다() { - Turn turn = new Turn(); - - turn.flip(); - turn.flip(); - - assertThat(turn.isOpponentTurn(Color.BLACK)).isTrue(); - } - - @Test - void 턴이_3번_정상적으로_변경된다() { - Turn turn = new Turn(); - - turn.flip(); - turn.flip(); - turn.flip(); - - assertThat(turn.isOpponentTurn(Color.WHITE)).isTrue(); - } -} From 03ca8cf867ce501fea9216debdfd982bd6eb8ea2 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sun, 24 Mar 2024 22:11:16 +0900 Subject: [PATCH 03/94] =?UTF-8?q?docs:=20=EA=B8=B0=EB=8A=A5=20=EC=9A=94?= =?UTF-8?q?=EA=B5=AC=EC=82=AC=ED=95=AD=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2133d8c8fc6..1b2f7d41853 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # java-chess -## 기능 요구사항 +## Step1, 2 기능 요구사항 ### 기물 공통 @@ -96,3 +96,24 @@ - [ ] 프로모션 : 폰이 상대 마지막 진영까지 도달하면 다른 기물로 변경할 수 있다. - [ ] 앙파상 - [ ] 캐슬링 + +## Step3, 4 기능 요구사항 + +### 체스 게임 + +- [ ] 양팀의 킹이 생존 여부를 확인한다. + - [ ] 킹이 죽으면 게임을 종료한다. +- [ ] 게임 점수를 계산한다. + - [ ] 각 팀의 점수를 따로 계산한다. + +### 점수 계산 + +- [ ] 현재까지 남아 있는 말에 따라 점수를 계산한다. +- [ ] queen은 9점, rook은 5점, bishop은 3점, knight는 2.5점이다. +- [ ] pawn의 기본 점수는 1점이다. + - [ ] 같은 세로줄에 같은 색의 폰이 있는 경우 0.5점을 준다. +- [ ] 킹이 없다면 0점이다. + +### 커맨드 + +- [ ] status: 각 팀의 점수를 출력한다. From dd3359efa0b7351a8243bb40f57f1917be811530 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sun, 24 Mar 2024 23:57:28 +0900 Subject: [PATCH 04/94] =?UTF-8?q?refactor:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EB=A5=BC=20=EC=9C=84=ED=95=9C=20Position=20=ED=94=BD=EC=8A=A4?= =?UTF-8?q?=EC=B3=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/Fixtures.java | 84 ++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/test/java/domain/Fixtures.java diff --git a/src/test/java/domain/Fixtures.java b/src/test/java/domain/Fixtures.java new file mode 100644 index 00000000000..10f97b10e68 --- /dev/null +++ b/src/test/java/domain/Fixtures.java @@ -0,0 +1,84 @@ +package domain; + +import domain.position.File; +import domain.position.Position; +import domain.position.Rank; + +@SuppressWarnings("unused") +public final class Fixtures { + + public static final Position A1 = new Position(File.A, Rank.ONE); + public static final Position A2 = new Position(File.A, Rank.TWO); + public static final Position A3 = new Position(File.A, Rank.THREE); + public static final Position A4 = new Position(File.A, Rank.FOUR); + public static final Position A5 = new Position(File.A, Rank.FIVE); + public static final Position A6 = new Position(File.A, Rank.SIX); + public static final Position A7 = new Position(File.A, Rank.SEVEN); + public static final Position A8 = new Position(File.A, Rank.EIGHT); + + public static final Position B1 = new Position(File.B, Rank.ONE); + public static final Position B2 = new Position(File.B, Rank.TWO); + public static final Position B3 = new Position(File.B, Rank.THREE); + public static final Position B4 = new Position(File.B, Rank.FOUR); + public static final Position B5 = new Position(File.B, Rank.FIVE); + public static final Position B6 = new Position(File.B, Rank.SIX); + public static final Position B7 = new Position(File.B, Rank.SEVEN); + public static final Position B8 = new Position(File.B, Rank.EIGHT); + + public static final Position C1 = new Position(File.C, Rank.ONE); + public static final Position C2 = new Position(File.C, Rank.TWO); + public static final Position C3 = new Position(File.C, Rank.THREE); + public static final Position C4 = new Position(File.C, Rank.FOUR); + public static final Position C5 = new Position(File.C, Rank.FIVE); + public static final Position C6 = new Position(File.C, Rank.SIX); + public static final Position C7 = new Position(File.C, Rank.SEVEN); + public static final Position C8 = new Position(File.C, Rank.EIGHT); + + public static final Position D1 = new Position(File.D, Rank.ONE); + public static final Position D2 = new Position(File.D, Rank.TWO); + public static final Position D3 = new Position(File.D, Rank.THREE); + public static final Position D4 = new Position(File.D, Rank.FOUR); + public static final Position D5 = new Position(File.D, Rank.FIVE); + public static final Position D6 = new Position(File.D, Rank.SIX); + public static final Position D7 = new Position(File.D, Rank.SEVEN); + public static final Position D8 = new Position(File.D, Rank.EIGHT); + + public static final Position E1 = new Position(File.E, Rank.ONE); + public static final Position E2 = new Position(File.E, Rank.TWO); + public static final Position E3 = new Position(File.E, Rank.THREE); + public static final Position E4 = new Position(File.E, Rank.FOUR); + public static final Position E5 = new Position(File.E, Rank.FIVE); + public static final Position E6 = new Position(File.E, Rank.SIX); + public static final Position E7 = new Position(File.E, Rank.SEVEN); + public static final Position E8 = new Position(File.E, Rank.EIGHT); + + public static final Position F1 = new Position(File.F, Rank.ONE); + public static final Position F2 = new Position(File.F, Rank.TWO); + public static final Position F3 = new Position(File.F, Rank.THREE); + public static final Position F4 = new Position(File.F, Rank.FOUR); + public static final Position F5 = new Position(File.F, Rank.FIVE); + public static final Position F6 = new Position(File.F, Rank.SIX); + public static final Position F7 = new Position(File.F, Rank.SEVEN); + public static final Position F8 = new Position(File.F, Rank.EIGHT); + + public static final Position G1 = new Position(File.G, Rank.ONE); + public static final Position G2 = new Position(File.G, Rank.TWO); + public static final Position G3 = new Position(File.G, Rank.THREE); + public static final Position G4 = new Position(File.G, Rank.FOUR); + public static final Position G5 = new Position(File.G, Rank.FIVE); + public static final Position G6 = new Position(File.G, Rank.SIX); + public static final Position G7 = new Position(File.G, Rank.SEVEN); + public static final Position G8 = new Position(File.G, Rank.EIGHT); + + public static final Position H1 = new Position(File.H, Rank.ONE); + public static final Position H2 = new Position(File.H, Rank.TWO); + public static final Position H3 = new Position(File.H, Rank.THREE); + public static final Position H4 = new Position(File.H, Rank.FOUR); + public static final Position H5 = new Position(File.H, Rank.FIVE); + public static final Position H6 = new Position(File.H, Rank.SIX); + public static final Position H7 = new Position(File.H, Rank.SEVEN); + public static final Position H8 = new Position(File.H, Rank.EIGHT); + + private Fixtures() { + } +} From 3721bdbbc30273adedab8ec0d664b0c08eee18d8 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 00:57:50 +0900 Subject: [PATCH 05/94] =?UTF-8?q?feat:=20Score=20=EA=B3=84=EC=82=B0=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 18 ++--- src/main/java/domain/board/Score.java | 77 ++++++++++++++++++++ src/main/java/domain/piece/Type.java | 22 ++++-- src/test/java/domain/board/ScoreTest.java | 88 +++++++++++++++++++++++ 4 files changed, 190 insertions(+), 15 deletions(-) create mode 100644 src/main/java/domain/board/Score.java create mode 100644 src/test/java/domain/board/ScoreTest.java diff --git a/README.md b/README.md index 1b2f7d41853..bf6bfbb1bc1 100644 --- a/README.md +++ b/README.md @@ -93,26 +93,26 @@ ### 추가 룰 -- [ ] 프로모션 : 폰이 상대 마지막 진영까지 도달하면 다른 기물로 변경할 수 있다. +- [ ] 프로모션 : 폰이 상대 마지막 진영까지 도달하면 다른 기물로 변경할 수 있다. - [ ] 앙파상 -- [ ] 캐슬링 +- [ ] 캐슬링 ## Step3, 4 기능 요구사항 ### 체스 게임 - [ ] 양팀의 킹이 생존 여부를 확인한다. - - [ ] 킹이 죽으면 게임을 종료한다. + - [ ] 킹이 죽으면 게임을 종료한다. - [ ] 게임 점수를 계산한다. - - [ ] 각 팀의 점수를 따로 계산한다. ### 점수 계산 -- [ ] 현재까지 남아 있는 말에 따라 점수를 계산한다. -- [ ] queen은 9점, rook은 5점, bishop은 3점, knight는 2.5점이다. -- [ ] pawn의 기본 점수는 1점이다. - - [ ] 같은 세로줄에 같은 색의 폰이 있는 경우 0.5점을 준다. -- [ ] 킹이 없다면 0점이다. +- [x] 현재까지 남아 있는 말에 따라 점수를 계산한다. + - [x] 각 팀의 점수를 따로 계산한다. +- [x] queen은 9점, rook은 5점, bishop은 3점, knight는 2.5점이다. +- [x] pawn의 기본 점수는 1점이다. + - [x] 같은 세로줄에 같은 색의 폰이 있는 경우 0.5점을 준다. +- [x] 킹이 없다면 0점이다. ### 커맨드 diff --git a/src/main/java/domain/board/Score.java b/src/main/java/domain/board/Score.java new file mode 100644 index 00000000000..50ded9dd063 --- /dev/null +++ b/src/main/java/domain/board/Score.java @@ -0,0 +1,77 @@ +package domain.board; + +import domain.piece.Color; +import domain.piece.Piece; +import domain.piece.Type; +import domain.position.File; +import domain.position.Position; + +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class Score { + private final double whiteScore; + private final double blackScore; + + private Score(final double whiteScore, final double blackScore) { + this.whiteScore = whiteScore; + this.blackScore = blackScore; + } + + public static Score calculate(final Map board) { + double whiteScore = calculateBoardScore(board, Color.WHITE); + double blackScore = calculateBoardScore(board, Color.BLACK); + return new Score(whiteScore, blackScore); + } + + public static double calculateBoardScore(final Map board, final Color color) { + if (hasNoKingPiece(board, color)) { + return 0; + } + return calculateTotalScore(board, color) - calculateDistinctFilesPenalty(board, color); + } + + private static boolean hasNoKingPiece(final Map board, final Color color) { + return getPiecesOfColor(board, color) + .noneMatch(positionPieceEntry -> positionPieceEntry.getValue().type() == Type.KING); + } + + private static double calculateTotalScore(final Map board, final Color color) { + return getPiecesOfColor(board, color) + .mapToDouble(positionPieceEntry -> positionPieceEntry.getValue().type().score()) + .sum(); + } + + private static double calculateDistinctFilesPenalty(final Map board, final Color color) { + final Map fileCounts = countPawnPiecesByFile(board, color); + + final long totalDuplicateFiles = fileCounts.values().stream() + .filter(count -> count > 1) + .reduce(0L, Long::sum); + + return totalDuplicateFiles * 0.5; + } + + private static Map countPawnPiecesByFile(final Map board, final Color color) { + return getPiecesOfColor(board, color) + .filter(entry -> entry.getValue().type() == Type.PAWN) + .collect(Collectors.groupingBy( + entry -> entry.getKey().file(), + Collectors.counting() + )); + } + + private static Stream> getPiecesOfColor(final Map board, final Color color) { + return board.entrySet().stream() + .filter(positionPieceEntry -> positionPieceEntry.getValue().color() == color); + } + + public double getWhiteScore() { + return whiteScore; + } + + public double getBlackScore() { + return blackScore; + } +} diff --git a/src/main/java/domain/piece/Type.java b/src/main/java/domain/piece/Type.java index 0301c9f2528..e5760bf4a88 100644 --- a/src/main/java/domain/piece/Type.java +++ b/src/main/java/domain/piece/Type.java @@ -1,10 +1,20 @@ package domain.piece; public enum Type { - KING, - QUEEN, - ROOK, - BISHOP, - KNIGHT, - PAWN; + KING(0.0), + QUEEN(9.0), + ROOK(5.0), + BISHOP(3.0), + KNIGHT(2.5), + PAWN(1.0); + + final double score; + + Type(final double score) { + this.score = score; + } + + public double score() { + return score; + } } diff --git a/src/test/java/domain/board/ScoreTest.java b/src/test/java/domain/board/ScoreTest.java new file mode 100644 index 00000000000..510476dae9d --- /dev/null +++ b/src/test/java/domain/board/ScoreTest.java @@ -0,0 +1,88 @@ +package domain.board; + +import domain.piece.Piece; +import domain.piece.nonpawn.Bishop; +import domain.piece.nonpawn.King; +import domain.piece.nonpawn.Knight; +import domain.piece.nonpawn.Queen; +import domain.piece.nonpawn.Rook; +import domain.piece.pawn.BlackPawn; +import domain.piece.pawn.WhitePawn; +import domain.position.Position; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static domain.Fixtures.*; +import static domain.piece.Color.BLACK; +import static domain.piece.Color.WHITE; +import static domain.piece.Type.BISHOP; +import static domain.piece.Type.KING; +import static domain.piece.Type.KNIGHT; +import static domain.piece.Type.PAWN; +import static domain.piece.Type.QUEEN; +import static domain.piece.Type.ROOK; +import static org.assertj.core.api.Assertions.assertThat; + +class ScoreTest { + @Test + void 모든_피스가_존재하면_점수는_38점이다() { + ChessBoard board = ChessBoardFactory.createInitialChessBoard(); + + Score score = Score.calculate(board.getBoard()); + + assertThat(score.getWhiteScore()).isEqualTo(38.0); + assertThat(score.getBlackScore()).isEqualTo(38.0); + } + + @Test + void 같은_세로_줄에_폰이_3개_존재하면_일점오점_이다() { + Map board = Map.of(A5, new WhitePawn(), A6, new WhitePawn(), A7, new WhitePawn(), + A8, new King(WHITE)); + + Score score = Score.calculate(board); + + double expectedWhiteScore = 0.5 * 3; + assertThat(score.getWhiteScore()).isEqualTo(expectedWhiteScore); + } + + @Test + void 같은_세로_줄에_폰이_3개_그리고_2개_그리고_1개_존재하면_삼점오점_이다() { + Map board = Map.of( + A5, new WhitePawn(), A6, new WhitePawn(), A7, new WhitePawn(), + B5, new WhitePawn(), B6, new WhitePawn(), + C5, new WhitePawn(), + A8, new King(WHITE) + ); + + Score score = Score.calculate(board); + + double expectedWhiteScore = 0.5 * 5 + 1.0; + assertThat(score.getWhiteScore()).isEqualTo(expectedWhiteScore); + } + + @Test + void 일부_피스가_존재하는_경우에_점수를_계산할_수_있다() { + var board = Map.ofEntries( + Map.entry(A7, new WhitePawn()), Map.entry(B7, new WhitePawn()), Map.entry(C7, new WhitePawn()), + Map.entry(D7, new WhitePawn()), Map.entry(E7, new WhitePawn()), Map.entry(F7, new WhitePawn()), + Map.entry(A8, new Rook(WHITE)), Map.entry(B8, new Bishop(WHITE)), Map.entry(C8, new Knight(WHITE)), + Map.entry(E8, new King(WHITE)), Map.entry(F8, new Queen(WHITE)), + Map.entry(A2, new BlackPawn()), Map.entry(B2, new BlackPawn()), Map.entry(C2, new BlackPawn()), + Map.entry(D2, new BlackPawn()), Map.entry(E2, new BlackPawn()), + Map.entry(A1, new Rook(BLACK)), Map.entry(B1, new Bishop(BLACK)), Map.entry(C1, new Knight(BLACK)), + Map.entry(H1, new Rook(BLACK)), Map.entry(G1, new Bishop(BLACK)), Map.entry(F1, new Knight(BLACK)), + Map.entry(E1, new King(BLACK)), Map.entry(D1, new Queen(BLACK)) + ); + + Score score = Score.calculate(board); + + double expectedWhiteScore = PAWN.score() * 6 + ROOK.score() * 1 + BISHOP.score() * 1 + + KNIGHT.score() * 1 + KING.score() + QUEEN.score(); + double expectedBlackScore = PAWN.score() * 5 + ROOK.score() * 2 + BISHOP.score() * 2 + + KNIGHT.score() * 2 + KING.score() + QUEEN.score(); + + assertThat(score.getWhiteScore()).isEqualTo(expectedWhiteScore); + assertThat(score.getBlackScore()).isEqualTo(expectedBlackScore); + } +} From c82a41f2db4c8eb6d6e0c64fc54c3c25715f32b4 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 01:00:36 +0900 Subject: [PATCH 06/94] =?UTF-8?q?feat:=20Score=20=EA=B3=84=EC=82=B0=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/domain/board/ChessBoard.java | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bf6bfbb1bc1..cc537347b3d 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ - [ ] 양팀의 킹이 생존 여부를 확인한다. - [ ] 킹이 죽으면 게임을 종료한다. -- [ ] 게임 점수를 계산한다. +- [x] 게임 점수를 계산한다. ### 점수 계산 diff --git a/src/main/java/domain/board/ChessBoard.java b/src/main/java/domain/board/ChessBoard.java index 328165e02e7..983ee0fac54 100644 --- a/src/main/java/domain/board/ChessBoard.java +++ b/src/main/java/domain/board/ChessBoard.java @@ -76,6 +76,10 @@ private Piece findPieceByPosition(final Position position) { return board.getOrDefault(position, Empty.getInstance()); } + public Score calculateScore() { + return Score.calculate(board); + } + public Map getBoard() { return Collections.unmodifiableMap(board); } From 1666be69f76f551567d4e9e2ed3d8a9478a4c8f5 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 01:10:10 +0900 Subject: [PATCH 07/94] =?UTF-8?q?feat:=20status=20=EC=BB=A4=EB=A7=A8?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../controller/command/StatusOnCommand.java | 18 ++++++++++++++++++ src/main/java/view/InputView.java | 4 ++++ src/main/java/view/MessageResolver.java | 13 ++++++++++--- src/main/java/view/OutputView.java | 8 +++++++- 5 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 src/main/java/controller/command/StatusOnCommand.java diff --git a/README.md b/README.md index cc537347b3d..ca86aa71893 100644 --- a/README.md +++ b/README.md @@ -116,4 +116,4 @@ ### 커맨드 -- [ ] status: 각 팀의 점수를 출력한다. +- [x] status: 각 팀의 점수를 출력한다. diff --git a/src/main/java/controller/command/StatusOnCommand.java b/src/main/java/controller/command/StatusOnCommand.java new file mode 100644 index 00000000000..47974c63dee --- /dev/null +++ b/src/main/java/controller/command/StatusOnCommand.java @@ -0,0 +1,18 @@ +package controller.command; + +import domain.board.ChessBoard; +import domain.board.Score; +import view.OutputView; + +public class StatusOnCommand implements Command{ + @Override + public void execute(final ChessBoard board, final OutputView outputView) { + Score score = board.calculateScore(); + outputView.printScore(score); + } + + @Override + public boolean isNotEnded() { + return true; + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index b975fdd5022..5f3a87ebee8 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -4,6 +4,7 @@ import controller.command.EndOnCommand; import controller.command.MoveOnCommand; import controller.command.StartOnCommand; +import controller.command.StatusOnCommand; import domain.position.Position; import java.util.Scanner; @@ -28,6 +29,9 @@ public Command readCommand() { if (hasSize(rawInput, 1) && "start".equals(rawInput[0])) { return new StartOnCommand(); } + if (hasSize(rawInput, 1) && "status".equals(rawInput[0])) { + return new StatusOnCommand(); + } if (hasSize(rawInput, 3) && "move".equals(rawInput[0])) { return new MoveOnCommand(resolvePosition(rawInput[1]), resolvePosition(rawInput[2])); } diff --git a/src/main/java/view/MessageResolver.java b/src/main/java/view/MessageResolver.java index 6db19f02dcd..af585a7dc49 100644 --- a/src/main/java/view/MessageResolver.java +++ b/src/main/java/view/MessageResolver.java @@ -1,6 +1,7 @@ package view; import domain.board.ChessBoard; +import domain.board.Score; import domain.piece.Piece; import domain.piece.Type; import domain.position.File; @@ -55,18 +56,18 @@ private String resolveOneRank(ChessBoard board, Rank targetRank) { return rankMessage.toString(); } - private void updateRankMessage(final StringBuilder rankMessage, final Map.Entry positionPieceEntry) { + private void updateRankMessage(StringBuilder rankMessage, Map.Entry positionPieceEntry) { Position position = resolvePosition(positionPieceEntry); Piece piece = resolvePiece(positionPieceEntry); File file = position.file(); rankMessage.setCharAt(file.order(), pieceDisplay(piece).charAt(0)); } - private Piece resolvePiece(final Map.Entry positionAndPiece) { + private Piece resolvePiece(Map.Entry positionAndPiece) { return positionAndPiece.getValue(); } - private Position resolvePosition(final Map.Entry positionAndPiece) { + private Position resolvePosition(Map.Entry positionAndPiece) { return positionAndPiece.getKey(); } @@ -77,4 +78,10 @@ private String pieceDisplay(Piece piece) { } return pieceName; } + + public String resolveScore(Score score) { + String whiteScoreMessage = String.format("WHITE 점수: %.1f", score.getWhiteScore()); + String blackScoreMessage = String.format("BLACK 점수: %.1f", score.getBlackScore()); + return String.join(LINE_SEPARATOR, whiteScoreMessage, blackScoreMessage); + } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 02b389052b3..6eae546541a 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -1,6 +1,7 @@ package view; import domain.board.ChessBoard; +import domain.board.Score; public class OutputView { private final MessageResolver messageResolver; @@ -18,7 +19,12 @@ public void printBoard(ChessBoard board) { System.out.println(boardRankMessage); } - public void printErrorMessage(final String errorMessage) { + public void printErrorMessage(String errorMessage) { System.out.println(errorMessage); } + + public void printScore(Score score) { + String scoreMessage = messageResolver.resolveScore(score); + System.out.println(scoreMessage); + } } From 0563ffb7b283594fc21575722dd2aad8940d8676 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 01:23:14 +0900 Subject: [PATCH 08/94] =?UTF-8?q?feat:=20king=EC=9D=B4=20=EC=A3=BD?= =?UTF-8?q?=EC=9C=BC=EB=A9=B4=20=EA=B2=8C=EC=9E=84=20=EC=A2=85=EB=A3=8C?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- src/main/java/controller/ChessController.java | 10 +++++++++- src/main/java/domain/board/ChessBoard.java | 7 +++++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ca86aa71893..f61cb8d407a 100644 --- a/README.md +++ b/README.md @@ -101,8 +101,8 @@ ### 체스 게임 -- [ ] 양팀의 킹이 생존 여부를 확인한다. - - [ ] 킹이 죽으면 게임을 종료한다. +- [x] 양팀의 킹이 생존 여부를 확인한다. + - [x] 킹이 죽으면 게임을 종료한다. - [x] 게임 점수를 계산한다. ### 점수 계산 diff --git a/src/main/java/controller/ChessController.java b/src/main/java/controller/ChessController.java index c64185f254d..8161d518a71 100644 --- a/src/main/java/controller/ChessController.java +++ b/src/main/java/controller/ChessController.java @@ -1,6 +1,7 @@ package controller; import controller.command.Command; +import controller.command.EndOnCommand; import domain.board.ChessBoard; import domain.board.ChessBoardFactory; import view.InputView; @@ -22,7 +23,7 @@ public void start() { Command command = readStartCommandUntilValid(); while (command.isNotEnded()) { command.execute(board, outputView); - command = readCommandUntilValid(); + command = readCommandIfGameNotEnded(board); } } @@ -35,6 +36,13 @@ private Command readStartCommandUntilValid() { } } + private Command readCommandIfGameNotEnded(final ChessBoard board) { + if (board.isKingNotExist()) { + return new EndOnCommand(); + } + return readCommandUntilValid(); + } + private Command readCommandUntilValid() { try { return inputView.readCommand(); diff --git a/src/main/java/domain/board/ChessBoard.java b/src/main/java/domain/board/ChessBoard.java index 983ee0fac54..58281f9bd03 100644 --- a/src/main/java/domain/board/ChessBoard.java +++ b/src/main/java/domain/board/ChessBoard.java @@ -3,6 +3,7 @@ import domain.piece.Color; import domain.piece.Empty; import domain.piece.Piece; +import domain.piece.Type; import domain.position.Position; import domain.position.Route; @@ -76,6 +77,12 @@ private Piece findPieceByPosition(final Position position) { return board.getOrDefault(position, Empty.getInstance()); } + public boolean isKingNotExist() { + return board.values().stream() + .filter(piece -> piece.type() == Type.KING) + .count() != 2; + } + public Score calculateScore() { return Score.calculate(board); } From fcb73d930c8b2eb1909c87b96883de98953840e1 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 14:21:06 +0900 Subject: [PATCH 09/94] =?UTF-8?q?feat:=20DB=20ConnectionManager=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/domain/dao/ConnectionManager.java | 23 +++++++++++++++++++ .../domain/dao/ConnectionManagerTest.java | 19 +++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/main/java/domain/dao/ConnectionManager.java create mode 100644 src/test/java/domain/dao/ConnectionManagerTest.java diff --git a/src/main/java/domain/dao/ConnectionManager.java b/src/main/java/domain/dao/ConnectionManager.java new file mode 100644 index 00000000000..80429ad79e2 --- /dev/null +++ b/src/main/java/domain/dao/ConnectionManager.java @@ -0,0 +1,23 @@ +package domain.dao; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +public class ConnectionManager { + private static final String SERVER = "localhost:13306"; + private static final String DATABASE = "chess"; + private static final String OPTION = "?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC"; + private static final String USERNAME = "root"; + private static final String PASSWORD = "root"; + + public Connection getConnection() { + try { + return DriverManager.getConnection("jdbc:mysql://" + SERVER + "/" + DATABASE + OPTION, USERNAME, PASSWORD); + } catch (final SQLException e) { + System.err.println("DB 연결 오류:" + e.getMessage()); + e.printStackTrace(); + return null; + } + } +} diff --git a/src/test/java/domain/dao/ConnectionManagerTest.java b/src/test/java/domain/dao/ConnectionManagerTest.java new file mode 100644 index 00000000000..52598a47ca3 --- /dev/null +++ b/src/test/java/domain/dao/ConnectionManagerTest.java @@ -0,0 +1,19 @@ +package domain.dao; + +import org.junit.jupiter.api.Test; + +import java.sql.SQLException; + +import static org.assertj.core.api.Assertions.assertThat; + +class ConnectionManagerTest { + @Test + void connectionTest() { + ConnectionManager connectionManager = new ConnectionManager(); + try (final var connection = connectionManager.getConnection()) { + assertThat(connection).isNotNull(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } +} From 04b07454de8aea882d37a06208744362d700a870 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 14:56:26 +0900 Subject: [PATCH 10/94] =?UTF-8?q?feat:=20PieceDto=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/dao/PieceDto.java | 27 ++++++++ src/main/java/domain/piece/Type.java | 35 ++++++++-- src/test/java/domain/dao/PieceDtoTest.java | 80 ++++++++++++++++++++++ 3 files changed, 135 insertions(+), 7 deletions(-) create mode 100644 src/main/java/domain/dao/PieceDto.java create mode 100644 src/test/java/domain/dao/PieceDtoTest.java diff --git a/src/main/java/domain/dao/PieceDto.java b/src/main/java/domain/dao/PieceDto.java new file mode 100644 index 00000000000..837830688f1 --- /dev/null +++ b/src/main/java/domain/dao/PieceDto.java @@ -0,0 +1,27 @@ +package domain.dao; + +import domain.piece.Color; +import domain.piece.Piece; +import domain.piece.Type; +import domain.position.File; +import domain.position.Position; +import domain.position.Rank; + +public record PieceDto( + String boardFile, + String boardRank, + String color, + String type +) { + public Position getPosition() { + final File file = File.fromName(boardFile); + final Rank rank = Rank.fromNumber(Integer.parseInt(boardRank)); + return new Position(file, rank); + } + + public Piece getPiece() { + final Color pieceColor = Color.valueOf(color); + final Type pieceType = Type.valueOf(type); + return pieceType.getPiece(pieceColor); + } +} diff --git a/src/main/java/domain/piece/Type.java b/src/main/java/domain/piece/Type.java index e5760bf4a88..39657584bc5 100644 --- a/src/main/java/domain/piece/Type.java +++ b/src/main/java/domain/piece/Type.java @@ -1,17 +1,38 @@ package domain.piece; +import domain.piece.nonpawn.Bishop; +import domain.piece.nonpawn.King; +import domain.piece.nonpawn.Knight; +import domain.piece.nonpawn.Queen; +import domain.piece.nonpawn.Rook; +import domain.piece.pawn.BlackPawn; +import domain.piece.pawn.WhitePawn; + +import java.util.function.Function; + public enum Type { - KING(0.0), - QUEEN(9.0), - ROOK(5.0), - BISHOP(3.0), - KNIGHT(2.5), - PAWN(1.0); + KING(0.0, King::new), + QUEEN(9.0, Queen::new), + ROOK(5.0, Rook::new), + BISHOP(3.0, Bishop::new), + KNIGHT(2.5, Knight::new), + PAWN(1.0, (color) -> { + if (color.isBlack()) { + return new BlackPawn(); + } + return new WhitePawn(); + }); final double score; + final Function getInstance; - Type(final double score) { + Type(final double score, final Function getInstance) { this.score = score; + this.getInstance = getInstance; + } + + public Piece getPiece(final Color color) { + return getInstance.apply(color); } public double score() { diff --git a/src/test/java/domain/dao/PieceDtoTest.java b/src/test/java/domain/dao/PieceDtoTest.java new file mode 100644 index 00000000000..62d6b77b352 --- /dev/null +++ b/src/test/java/domain/dao/PieceDtoTest.java @@ -0,0 +1,80 @@ +package domain.dao; + +import domain.piece.nonpawn.Bishop; +import domain.piece.nonpawn.King; +import domain.piece.nonpawn.Knight; +import domain.piece.nonpawn.Queen; +import domain.piece.nonpawn.Rook; +import domain.piece.pawn.BlackPawn; +import domain.piece.pawn.WhitePawn; +import domain.position.File; +import domain.position.Position; +import domain.position.Rank; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class PieceDtoTest { + @Nested + class 피스_변환 { + @Test + void KING으로_변환한다() { + PieceDto pieceDto = new PieceDto("A", "1", "WHITE", "KING"); + + assertThat(pieceDto.getPiece()).isInstanceOf(King.class); + } + + @Test + void QUEEN으로_변환한다() { + PieceDto pieceDto = new PieceDto("A", "1", "WHITE", "QUEEN"); + + assertThat(pieceDto.getPiece()).isInstanceOf(Queen.class); + } + + @Test + void BISHOP으로_변환한다() { + PieceDto pieceDto = new PieceDto("A", "1", "WHITE", "BISHOP"); + + assertThat(pieceDto.getPiece()).isInstanceOf(Bishop.class); + } + + @Test + void ROOK으로_변환한다() { + PieceDto pieceDto = new PieceDto("A", "1", "WHITE", "ROOK"); + + assertThat(pieceDto.getPiece()).isInstanceOf(Rook.class); + } + + @Test + void KNIGHT으로_변환한다() { + PieceDto pieceDto = new PieceDto("A", "1", "WHITE", "KNIGHT"); + + assertThat(pieceDto.getPiece()).isInstanceOf(Knight.class); + } + + @Test + void WHITE_PAWN으로_변환한다() { + PieceDto pieceDto = new PieceDto("A", "1", "WHITE", "PAWN"); + + assertThat(pieceDto.getPiece()).isInstanceOf(WhitePawn.class); + } + + @Test + void BLACK_PAWN으로_변환한다() { + PieceDto pieceDto = new PieceDto("A", "1", "BLACK", "PAWN"); + + assertThat(pieceDto.getPiece()).isInstanceOf(BlackPawn.class); + } + } + + @Nested + class 위치_변환 { + @Test + void 위치를_만든다() { + PieceDto pieceDto = new PieceDto("a", "1", "WHITE", "PAWN"); + + assertThat(pieceDto.getPosition()).isEqualTo(new Position(File.A, Rank.ONE)); + } + } +} From 3f7cb1cb0d9cdda6fbce12adbe16712447fb7822 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 15:09:20 +0900 Subject: [PATCH 11/94] =?UTF-8?q?chore:=20DB=EB=A5=BC=20=EC=9C=84=ED=95=9C?= =?UTF-8?q?=20=ED=99=98=EA=B2=BD=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + docker/docker-compose.yml | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 docker/docker-compose.yml diff --git a/build.gradle b/build.gradle index 3697236c6fb..8c605072e94 100644 --- a/build.gradle +++ b/build.gradle @@ -13,6 +13,7 @@ dependencies { testImplementation platform('org.assertj:assertj-bom:3.25.1') testImplementation('org.junit.jupiter:junit-jupiter') testImplementation('org.assertj:assertj-core') + runtimeOnly("com.mysql:mysql-connector-j:8.3.0") } java { diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 00000000000..558a1d5a53f --- /dev/null +++ b/docker/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 From e4e7951ad1bc7bf04ee94b9a0a1d27acf70fefdb Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 15:10:21 +0900 Subject: [PATCH 12/94] =?UTF-8?q?feat:=20chess=20SQL=EB=AC=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/chess.sql | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/main/resources/chess.sql diff --git a/src/main/resources/chess.sql b/src/main/resources/chess.sql new file mode 100644 index 00000000000..2610db5099f --- /dev/null +++ b/src/main/resources/chess.sql @@ -0,0 +1,7 @@ +create table piece ( + board_file varchar(1) not null, + board_rank varchar(1) not null, + color varchar(5) not null, + type varchar(6) not null, + primary key (board_file, board_rank) +) From f47c296918db732ecfb12a739841c5d392cf3f86 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 15:11:20 +0900 Subject: [PATCH 13/94] =?UTF-8?q?feat:=20PieceDao=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/dao/PieceDao.java | 60 ++++++++++++++++++++++ src/test/java/domain/dao/PieceDaoTest.java | 36 +++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/main/java/domain/dao/PieceDao.java create mode 100644 src/test/java/domain/dao/PieceDaoTest.java diff --git a/src/main/java/domain/dao/PieceDao.java b/src/main/java/domain/dao/PieceDao.java new file mode 100644 index 00000000000..6f3d882b32e --- /dev/null +++ b/src/main/java/domain/dao/PieceDao.java @@ -0,0 +1,60 @@ +package domain.dao; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class PieceDao { + private final ConnectionManager connectionManager; + + private PieceDao(final ConnectionManager connectionManager) { + this.connectionManager = connectionManager; + } + + public PieceDao() { + this(new ConnectionManager()); + } + + public void add(final PieceDto piece) { + final var query = "INSERT INTO piece VALUES(?, ?, ?, ?)"; + try (final var connection = connectionManager.getConnection(); + final var preparedStatement = connection.prepareStatement(query)) { + preparedStatement.setString(1, piece.boardFile()); + preparedStatement.setString(2, piece.boardRank()); + preparedStatement.setString(3, piece.color()); + preparedStatement.setString(4, piece.type()); + preparedStatement.executeUpdate(); + } catch (final SQLException e) { + throw new RuntimeException(e); + } + } + + public PieceDto find(final String file, final String rank) { + final var query = "SELECT * FROM piece WHERE board_file = ? and board_rank = ?"; + try (final var connection = connectionManager.getConnection(); + final var preparedStatement = connection.prepareStatement(query)) { + preparedStatement.setString(1, file); + preparedStatement.setString(2, rank); + final ResultSet resultSet = preparedStatement.executeQuery(); + if (resultSet.next()) { + return new PieceDto(file, + rank, + resultSet.getString("color"), + resultSet.getString("type") + ); + } + } catch (final SQLException e) { + throw new RuntimeException(e); + } + return null; + } + + public void deleteAll() { + final var query = "DELETE FROM piece"; + try (final var connection = connectionManager.getConnection(); + final var preparedStatement = connection.prepareStatement(query)) { + preparedStatement.executeUpdate(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/test/java/domain/dao/PieceDaoTest.java b/src/test/java/domain/dao/PieceDaoTest.java new file mode 100644 index 00000000000..4533cb7fcfb --- /dev/null +++ b/src/test/java/domain/dao/PieceDaoTest.java @@ -0,0 +1,36 @@ +package domain.dao; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class PieceDaoTest { + private final PieceDao pieceDao = new PieceDao(); + + @AfterEach + void rollback() { + pieceDao.deleteAll(); + } + + @Test + void 피스를_저장한다() { + final var pieceDto = new PieceDto("A", "3", "WHITE", "PAWN"); + + pieceDao.add(pieceDto); + PieceDto findPieceDto = pieceDao.find("A", "3"); + + assertThat(findPieceDto).isEqualTo(pieceDto); + } + + @Test + void 피스를_찾는다() { + final var pieceDto = new PieceDto("A", "3", "WHITE", "PAWN"); + pieceDao.add(pieceDto); + + PieceDto findPiece = pieceDao.find("A", "3"); + + assertThat(findPiece.color()).isEqualTo("WHITE"); + assertThat(findPiece.type()).isEqualTo("PAWN"); + } +} From ece313bb382ac60968c2877ac72c495f13834e14 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 15:36:36 +0900 Subject: [PATCH 14/94] =?UTF-8?q?feat:=20=EB=8F=84=EB=A9=94=EC=9D=B8?= =?UTF-8?q?=EC=97=90=EC=84=9C=20DTO=EB=A1=9C=20=EB=B3=80=ED=99=98=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/dao/PieceDto.java | 9 +++++++++ src/main/java/domain/position/Rank.java | 4 ++++ src/test/java/domain/dao/PieceDtoTest.java | 23 ++++++++++++---------- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/main/java/domain/dao/PieceDto.java b/src/main/java/domain/dao/PieceDto.java index 837830688f1..d27da32feb1 100644 --- a/src/main/java/domain/dao/PieceDto.java +++ b/src/main/java/domain/dao/PieceDto.java @@ -13,6 +13,15 @@ public record PieceDto( String color, String type ) { + public static PieceDto of(Position position, Piece piece) { + return new PieceDto( + position.file().name(), + position.rank().number(), + piece.color().name(), + piece.type().name() + ); + } + public Position getPosition() { final File file = File.fromName(boardFile); final Rank rank = Rank.fromNumber(Integer.parseInt(boardRank)); diff --git a/src/main/java/domain/position/Rank.java b/src/main/java/domain/position/Rank.java index d8f82bf61c8..8c5da658961 100644 --- a/src/main/java/domain/position/Rank.java +++ b/src/main/java/domain/position/Rank.java @@ -55,4 +55,8 @@ boolean isSame(final Rank rank) { int subtract(final Rank rank) { return this.number - rank.number; } + + public String number() { + return String.valueOf(number); + } } diff --git a/src/test/java/domain/dao/PieceDtoTest.java b/src/test/java/domain/dao/PieceDtoTest.java index 62d6b77b352..5a187a9472d 100644 --- a/src/test/java/domain/dao/PieceDtoTest.java +++ b/src/test/java/domain/dao/PieceDtoTest.java @@ -1,5 +1,7 @@ package domain.dao; +import domain.piece.Color; +import domain.piece.Piece; import domain.piece.nonpawn.Bishop; import domain.piece.nonpawn.King; import domain.piece.nonpawn.Knight; @@ -16,6 +18,17 @@ import static org.assertj.core.api.Assertions.assertThat; class PieceDtoTest { + @Test + void 도메인에서_DTO로_변환한다() { + Position position = new Position(File.A, Rank.ONE); + Piece piece = new King(Color.WHITE); + + PieceDto pieceDto = PieceDto.of(position, piece); + + PieceDto expected = new PieceDto("A", "1", "WHITE", "KING"); + assertThat(pieceDto).isEqualTo(expected); + } + @Nested class 피스_변환 { @Test @@ -67,14 +80,4 @@ class 피스_변환 { assertThat(pieceDto.getPiece()).isInstanceOf(BlackPawn.class); } } - - @Nested - class 위치_변환 { - @Test - void 위치를_만든다() { - PieceDto pieceDto = new PieceDto("a", "1", "WHITE", "PAWN"); - - assertThat(pieceDto.getPosition()).isEqualTo(new Position(File.A, Rank.ONE)); - } - } } From 910d23059fb625fd20e818f0ba6434061620dcf5 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 16:03:26 +0900 Subject: [PATCH 15/94] =?UTF-8?q?feat:=20=ED=94=BC=EC=8A=A4=EB=A5=BC=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/dao/PieceDao.java | 23 ++++++++++++++++++++++ src/test/java/domain/dao/PieceDaoTest.java | 14 +++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/main/java/domain/dao/PieceDao.java b/src/main/java/domain/dao/PieceDao.java index 6f3d882b32e..7e4c5103042 100644 --- a/src/main/java/domain/dao/PieceDao.java +++ b/src/main/java/domain/dao/PieceDao.java @@ -1,7 +1,11 @@ package domain.dao; +import java.sql.Connection; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; public class PieceDao { private final ConnectionManager connectionManager; @@ -48,6 +52,25 @@ public PieceDto find(final String file, final String rank) { return null; } + public List findAll() { + final List pieces = new ArrayList<>(); + final String query = "SELECT * FROM piece"; + try (final Connection connection = connectionManager.getConnection(); + final PreparedStatement preparedStatement = connection.prepareStatement(query)) { + final ResultSet resultSet = preparedStatement.executeQuery(); + while (resultSet.next()) { + String file = resultSet.getString("board_file"); + String rank = resultSet.getString("board_rank"); + String color = resultSet.getString("color"); + String type = resultSet.getString("type"); + pieces.add(new PieceDto(file, rank, color, type)); + } + } catch (final SQLException e) { + throw new RuntimeException(e); + } + return pieces; + } + public void deleteAll() { final var query = "DELETE FROM piece"; try (final var connection = connectionManager.getConnection(); diff --git a/src/test/java/domain/dao/PieceDaoTest.java b/src/test/java/domain/dao/PieceDaoTest.java index 4533cb7fcfb..40197f3d33a 100644 --- a/src/test/java/domain/dao/PieceDaoTest.java +++ b/src/test/java/domain/dao/PieceDaoTest.java @@ -33,4 +33,18 @@ void rollback() { assertThat(findPiece.color()).isEqualTo("WHITE"); assertThat(findPiece.type()).isEqualTo("PAWN"); } + + @Test + void 피스를_모두_찾는다() { + final var pieceDtoA = new PieceDto("A", "3", "WHITE", "PAWN"); + final var pieceDtoB = new PieceDto("B", "5", "BLACK", "PAWN"); + final var pieceDtoC = new PieceDto("C", "7", "BLACK", "KING"); + pieceDao.add(pieceDtoA); + pieceDao.add(pieceDtoB); + pieceDao.add(pieceDtoC); + + assertThat(pieceDao.findAll()) + .containsExactlyInAnyOrder(pieceDtoA, pieceDtoB, pieceDtoC); + + } } From 8f7258fc93623fe20c06fc363152016780f5a6a8 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 16:04:58 +0900 Subject: [PATCH 16/94] =?UTF-8?q?feat:=20=ED=94=BC=EC=8A=A4=20=EA=B0=9C?= =?UTF-8?q?=EC=88=98=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/dao/PieceDao.java | 14 ++++++++++++++ src/test/java/domain/dao/PieceDaoTest.java | 11 +++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/main/java/domain/dao/PieceDao.java b/src/main/java/domain/dao/PieceDao.java index 7e4c5103042..aac0e3163d8 100644 --- a/src/main/java/domain/dao/PieceDao.java +++ b/src/main/java/domain/dao/PieceDao.java @@ -80,4 +80,18 @@ public void deleteAll() { throw new RuntimeException(e); } } + + public int count() { + final var query = "SELECT COUNT(*) AS count FROM piece"; + try (final var connection = connectionManager.getConnection(); + final var preparedStatement = connection.prepareStatement(query)) { + ResultSet resultSet = preparedStatement.executeQuery(); + if (resultSet.next()) { + return Integer.parseInt(resultSet.getString("count")); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + return 0; + } } diff --git a/src/test/java/domain/dao/PieceDaoTest.java b/src/test/java/domain/dao/PieceDaoTest.java index 40197f3d33a..624ebee8655 100644 --- a/src/test/java/domain/dao/PieceDaoTest.java +++ b/src/test/java/domain/dao/PieceDaoTest.java @@ -45,6 +45,17 @@ void rollback() { assertThat(pieceDao.findAll()) .containsExactlyInAnyOrder(pieceDtoA, pieceDtoB, pieceDtoC); + } + + @Test + void 저장된_피스_개수를_센다() { + final var pieceDtoA = new PieceDto("A", "3", "WHITE", "PAWN"); + final var pieceDtoB = new PieceDto("B", "5", "BLACK", "PAWN"); + final var pieceDtoC = new PieceDto("C", "7", "BLACK", "KING"); + pieceDao.add(pieceDtoA); + pieceDao.add(pieceDtoB); + pieceDao.add(pieceDtoC); + assertThat(pieceDao.count()).isEqualTo(3); } } From a2693af0cffa8276d30ab7029672ecd137f4552c Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 16:21:25 +0900 Subject: [PATCH 17/94] =?UTF-8?q?refactor:=20view=EC=97=90=20=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EA=B0=92=20File=20=ED=95=84=EB=93=9C=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/position/File.java | 29 ++++++++++++------------- src/main/java/view/InputView.java | 2 +- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/main/java/domain/position/File.java b/src/main/java/domain/position/File.java index 73d9f86cbc4..50790c1c8ea 100644 --- a/src/main/java/domain/position/File.java +++ b/src/main/java/domain/position/File.java @@ -10,28 +10,27 @@ import static java.lang.Math.min; public enum File { - A("a", 0), - B("b", 1), - C("c", 2), - D("d", 3), - E("e", 4), - F("f", 5), - G("g", 6), - H("h", 7); + A(0), + B(1), + C(2), + D(3), + E(4), + F(5), + G(6), + H(7); - private final String name; private final int order; - File(String name, int order) { - this.name = name; + File(int order) { this.order = order; } public static File fromName(final String name) { - return Arrays.stream(values()) - .filter(file -> file.name.equals(name)) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("존재하지 않은 file입니다.")); + try { + return File.valueOf(name); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("존재하지 않은 file입니다."); + } } public static File fromOrder(final int order) { diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 5f3a87ebee8..5b85506b943 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -42,7 +42,7 @@ public Command readCommand() { } private Position resolvePosition(String position) { - String file = position.substring(0, 1); + String file = position.substring(0, 1).toUpperCase(); String rank = position.substring(1); try { return new Position(file, Integer.parseInt(rank)); From 9a3592a6a13e21dafa4d71042b3fb423349321a7 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 16:27:01 +0900 Subject: [PATCH 18/94] =?UTF-8?q?rename:=20SQL=20=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=EB=A6=BD=ED=8A=B8=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/{chess.sql => piece.sql} | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) rename src/main/resources/{chess.sql => piece.sql} (55%) diff --git a/src/main/resources/chess.sql b/src/main/resources/piece.sql similarity index 55% rename from src/main/resources/chess.sql rename to src/main/resources/piece.sql index 2610db5099f..e8c1f77a4ea 100644 --- a/src/main/resources/chess.sql +++ b/src/main/resources/piece.sql @@ -1,7 +1,8 @@ -create table piece ( +create table piece +( board_file varchar(1) not null, board_rank varchar(1) not null, - color varchar(5) not null, - type varchar(6) not null, + color varchar(5) not null, + type varchar(6) not null, primary key (board_file, board_rank) ) From 1286a69e88cd4c59b2a836ce0db8a961f4d38fda Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 16:28:43 +0900 Subject: [PATCH 19/94] =?UTF-8?q?feat:=20turn=20SQL=EB=AC=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/turn.sql | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/main/resources/turn.sql diff --git a/src/main/resources/turn.sql b/src/main/resources/turn.sql new file mode 100644 index 00000000000..2e49e440995 --- /dev/null +++ b/src/main/resources/turn.sql @@ -0,0 +1,5 @@ +create table turn +( + color varchar(5) not null, + primary key (color) +) From 805250db8865d8ee481717f2d9a34252c8a13980 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 16:29:13 +0900 Subject: [PATCH 20/94] =?UTF-8?q?docs:=20DB=20=EC=A0=80=EC=9E=A5=EC=97=90?= =?UTF-8?q?=20=EB=8C=80=ED=95=9C=20=EA=B8=B0=EB=8A=A5=20=EC=9A=94=EA=B5=AC?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f61cb8d407a..2c5ae96c1f4 100644 --- a/README.md +++ b/README.md @@ -116,4 +116,23 @@ ### 커맨드 -- [x] status: 각 팀의 점수를 출력한다. +- start + - [x] 체스판을 출력한다. +- move + - [x] 말을 움직인다. + - [x] 체스판을 출력한다. +- status + - [x] 각 팀의 점수를 출력한다. +- end + - [ ] 게임을 종료한다. + - [ ] 체스판을 출력한다. + - [ ] 각 팀의 점수를 출력한다. + +### 체스 게임 상태 저장 + +- [ ] 게임이 시작될 때 체스판을 만든다. + - [ ] DB에 저장된 데이터가 존재하면 불러온다. + - [ ] DB에 저장된 데이터가 없으면 체스판을 새로 만든다. +- [ ] 게임이 종료되면 기존 데이터를 모두 삭제한다. +- [ ] 킹이 죽지 않았으면 현재 체스판 데이터를 모두 저장한다. +- [ ] 현재 누구의 턴인지 저장한다. From e44402bfd4a281c6c944d42f9fbdecde43f616ad Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 16:51:22 +0900 Subject: [PATCH 21/94] =?UTF-8?q?refactor:=20=ED=85=8C=EC=9D=B4=EB=B8=94?= =?UTF-8?q?=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/{piece.sql => pieces.sql} | 2 +- src/main/resources/{turn.sql => turns.sql} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/main/resources/{piece.sql => pieces.sql} (90%) rename src/main/resources/{turn.sql => turns.sql} (75%) diff --git a/src/main/resources/piece.sql b/src/main/resources/pieces.sql similarity index 90% rename from src/main/resources/piece.sql rename to src/main/resources/pieces.sql index e8c1f77a4ea..db3702e2216 100644 --- a/src/main/resources/piece.sql +++ b/src/main/resources/pieces.sql @@ -1,4 +1,4 @@ -create table piece +create table pieces ( board_file varchar(1) not null, board_rank varchar(1) not null, diff --git a/src/main/resources/turn.sql b/src/main/resources/turns.sql similarity index 75% rename from src/main/resources/turn.sql rename to src/main/resources/turns.sql index 2e49e440995..2a0d2f44240 100644 --- a/src/main/resources/turn.sql +++ b/src/main/resources/turns.sql @@ -1,4 +1,4 @@ -create table turn +create table turns ( color varchar(5) not null, primary key (color) From e4c240611bf079d07849d96b2e66f37ff2ea59d1 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 16:54:50 +0900 Subject: [PATCH 22/94] =?UTF-8?q?refactor:=20=ED=85=8C=EC=9D=B4=EB=B8=94?= =?UTF-8?q?=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/dao/PieceDao.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/domain/dao/PieceDao.java b/src/main/java/domain/dao/PieceDao.java index aac0e3163d8..23967b83e1a 100644 --- a/src/main/java/domain/dao/PieceDao.java +++ b/src/main/java/domain/dao/PieceDao.java @@ -8,6 +8,7 @@ import java.util.List; public class PieceDao { + private static final String tableName = "pieces"; private final ConnectionManager connectionManager; private PieceDao(final ConnectionManager connectionManager) { @@ -19,7 +20,7 @@ public PieceDao() { } public void add(final PieceDto piece) { - final var query = "INSERT INTO piece VALUES(?, ?, ?, ?)"; + final var query = "INSERT INTO " + tableName + " VALUES(?, ?, ?, ?)"; try (final var connection = connectionManager.getConnection(); final var preparedStatement = connection.prepareStatement(query)) { preparedStatement.setString(1, piece.boardFile()); @@ -33,7 +34,7 @@ public void add(final PieceDto piece) { } public PieceDto find(final String file, final String rank) { - final var query = "SELECT * FROM piece WHERE board_file = ? and board_rank = ?"; + final var query = "SELECT * FROM " + tableName + " WHERE board_file = ? and board_rank = ?"; try (final var connection = connectionManager.getConnection(); final var preparedStatement = connection.prepareStatement(query)) { preparedStatement.setString(1, file); @@ -54,7 +55,7 @@ public PieceDto find(final String file, final String rank) { public List findAll() { final List pieces = new ArrayList<>(); - final String query = "SELECT * FROM piece"; + final String query = "SELECT * FROM " + tableName; try (final Connection connection = connectionManager.getConnection(); final PreparedStatement preparedStatement = connection.prepareStatement(query)) { final ResultSet resultSet = preparedStatement.executeQuery(); @@ -72,7 +73,7 @@ public List findAll() { } public void deleteAll() { - final var query = "DELETE FROM piece"; + final var query = "DELETE FROM " + tableName; try (final var connection = connectionManager.getConnection(); final var preparedStatement = connection.prepareStatement(query)) { preparedStatement.executeUpdate(); @@ -82,7 +83,7 @@ public void deleteAll() { } public int count() { - final var query = "SELECT COUNT(*) AS count FROM piece"; + final var query = "SELECT COUNT(*) AS count FROM " + tableName; try (final var connection = connectionManager.getConnection(); final var preparedStatement = connection.prepareStatement(query)) { ResultSet resultSet = preparedStatement.executeQuery(); From e7f427e8f274050f04b02b70a5fe17bfa2551870 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 16:55:54 +0900 Subject: [PATCH 23/94] =?UTF-8?q?feat:=20TurnDao=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/dao/TurnDao.java | 48 +++++++++++++++++++++++ src/test/java/domain/dao/TurnDaoTest.java | 17 ++++++++ 2 files changed, 65 insertions(+) create mode 100644 src/main/java/domain/dao/TurnDao.java create mode 100644 src/test/java/domain/dao/TurnDaoTest.java diff --git a/src/main/java/domain/dao/TurnDao.java b/src/main/java/domain/dao/TurnDao.java new file mode 100644 index 00000000000..4653f6d11ff --- /dev/null +++ b/src/main/java/domain/dao/TurnDao.java @@ -0,0 +1,48 @@ +package domain.dao; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class TurnDao { + private static final String tableName = "turns"; + private final ConnectionManager connectionManager; + + private TurnDao(final ConnectionManager connectionManager) { + this.connectionManager = connectionManager; + } + + public TurnDao() { + this(new ConnectionManager()); + } + + public String find() { + final var query = "SELECT * FROM " + tableName; + try (final var connection = connectionManager.getConnection(); + final var prepareStatement = connection.prepareStatement(query)) { + ResultSet resultSet = prepareStatement.executeQuery(); + if (resultSet.next()) { + return resultSet.getString("color"); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + return null; + } + + public void update(String color) { + final String deleteQuery = "DELETE FROM " + tableName; + final String insertQuery = "INSERT INTO " + tableName + " (color) VALUES (?)"; + try (final Connection connection = connectionManager.getConnection(); + final PreparedStatement deleteStatement = connection.prepareStatement(deleteQuery); + final PreparedStatement insertStatement = connection.prepareStatement(insertQuery)) { + deleteStatement.executeUpdate(); + + insertStatement.setString(1, color); + insertStatement.executeUpdate(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/test/java/domain/dao/TurnDaoTest.java b/src/test/java/domain/dao/TurnDaoTest.java new file mode 100644 index 00000000000..f1fa722f9e9 --- /dev/null +++ b/src/test/java/domain/dao/TurnDaoTest.java @@ -0,0 +1,17 @@ +package domain.dao; + +import domain.piece.Color; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class TurnDaoTest { + @Test + void 턴을_저장한다() { + TurnDao turnDao = new TurnDao(); + + turnDao.update(Color.WHITE.name()); + + assertThat(turnDao.find()).isEqualTo("WHITE"); + } +} From 5819994daa35c39dea46f6b93fa7320dd593ed22 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 21:30:11 +0900 Subject: [PATCH 24/94] =?UTF-8?q?feat:=20=EC=9D=B4=EC=A0=84=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=20=EC=83=81=ED=83=9C=EB=A5=BC=20DB=EC=97=90=EC=84=9C?= =?UTF-8?q?=20=EB=B6=88=EB=9F=AC=EC=98=A4=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 13 +++++---- src/main/java/controller/ChessController.java | 27 ++++++++++++++++++- src/main/java/domain/board/ChessBoard.java | 6 ++++- .../java/domain/board/ChessBoardFactory.java | 10 +++++++ 4 files changed, 49 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 2c5ae96c1f4..562acc5df99 100644 --- a/README.md +++ b/README.md @@ -127,12 +127,15 @@ - [ ] 게임을 종료한다. - [ ] 체스판을 출력한다. - [ ] 각 팀의 점수를 출력한다. +- (추가) 킹이 죽으면 게임은 자동으로 종료된다. ### 체스 게임 상태 저장 -- [ ] 게임이 시작될 때 체스판을 만든다. - - [ ] DB에 저장된 데이터가 존재하면 불러온다. - - [ ] DB에 저장된 데이터가 없으면 체스판을 새로 만든다. -- [ ] 게임이 종료되면 기존 데이터를 모두 삭제한다. +- [x] 게임이 시작될 때 체스판을 만든다. + - [x] DB에 저장된 데이터가 존재하면 불러온다. + - [x] DB에 저장된 데이터가 없으면 체스판을 새로 만든다. +- [x] 게임이 종료되면 기존 데이터를 모두 삭제한다. - [ ] 킹이 죽지 않았으면 현재 체스판 데이터를 모두 저장한다. -- [ ] 현재 누구의 턴인지 저장한다. +- [ ] 킹이 죽으면 모든 테이터를 삭제한다. + - [ ] 보드 데이터 삭제 + - [ ] 턴 데이터 삭제 diff --git a/src/main/java/controller/ChessController.java b/src/main/java/controller/ChessController.java index 8161d518a71..98874af9869 100644 --- a/src/main/java/controller/ChessController.java +++ b/src/main/java/controller/ChessController.java @@ -4,6 +4,12 @@ import controller.command.EndOnCommand; import domain.board.ChessBoard; import domain.board.ChessBoardFactory; +import domain.dao.PieceDao; +import domain.dao.PieceDto; +import domain.dao.TurnDao; +import domain.piece.Color; +import domain.piece.Piece; +import domain.position.Position; import view.InputView; import view.OutputView; @@ -17,14 +23,33 @@ public ChessController(InputView inputView, OutputView outputView) { } public void start() { + PieceDao pieceDao = new PieceDao(); + TurnDao turnDao = new TurnDao(); + outputView.printGameGuideMessage(); - final ChessBoard board = ChessBoardFactory.createInitialChessBoard(); + final ChessBoard board = createChessBoard(pieceDao, turnDao); Command command = readStartCommandUntilValid(); while (command.isNotEnded()) { command.execute(board, outputView); command = readCommandIfGameNotEnded(board); } + + pieceDao.deleteAll(); + for (var positionAndPiece : board.getBoard().entrySet()) { + Position position = positionAndPiece.getKey(); + Piece piece = positionAndPiece.getValue(); + pieceDao.add(PieceDto.of(position, piece)); + } + turnDao.update(board.getTurn().name()); + } + + private ChessBoard createChessBoard(PieceDao pieceDao, TurnDao turnDao) { + if (pieceDao.count() != 0) { + String color = turnDao.find(); + return ChessBoardFactory.loadPreviousChessBoard(pieceDao.findAll(), Color.valueOf(color)); + } + return ChessBoardFactory.createInitialChessBoard(); } private Command readStartCommandUntilValid() { diff --git a/src/main/java/domain/board/ChessBoard.java b/src/main/java/domain/board/ChessBoard.java index 58281f9bd03..cd8684e0a02 100644 --- a/src/main/java/domain/board/ChessBoard.java +++ b/src/main/java/domain/board/ChessBoard.java @@ -15,7 +15,7 @@ public class ChessBoard { private final Map board; private Color turn; - private ChessBoard(Map board, Color color) { + public ChessBoard(Map board, Color color) { this.board = board; this.turn = color; } @@ -90,4 +90,8 @@ public Score calculateScore() { public Map getBoard() { return Collections.unmodifiableMap(board); } + + public Color getTurn() { + return this.turn; + } } diff --git a/src/main/java/domain/board/ChessBoardFactory.java b/src/main/java/domain/board/ChessBoardFactory.java index cff59d6894b..0a792737cf5 100644 --- a/src/main/java/domain/board/ChessBoardFactory.java +++ b/src/main/java/domain/board/ChessBoardFactory.java @@ -1,5 +1,6 @@ package domain.board; +import domain.dao.PieceDto; import domain.piece.Color; import domain.piece.Piece; import domain.piece.nonpawn.Bishop; @@ -16,6 +17,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; public class ChessBoardFactory { private static final int SPECIAL_PIECE_SIZE = 8; @@ -41,4 +43,12 @@ public static ChessBoard createInitialChessBoard() { } return new ChessBoard(pieceMap); } + + public static ChessBoard loadPreviousChessBoard(List pieceDtos, final Color color) { + return pieceDtos.stream() + .collect(Collectors.collectingAndThen(Collectors.toMap( + PieceDto::getPosition, + PieceDto::getPiece + ), board -> new ChessBoard(board, color))); + } } From a04538784121e3c5e41680eab61ff96c3fbe60b6 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 21:38:16 +0900 Subject: [PATCH 25/94] =?UTF-8?q?docs:=20=EC=B2=B4=EC=8A=A4=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=20=EC=A0=84=EB=B0=98=EC=A0=81=EC=9D=B8=20=ED=9D=90?= =?UTF-8?q?=EB=A6=84=20=EC=9E=AC=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 562acc5df99..84c44589b47 100644 --- a/README.md +++ b/README.md @@ -101,9 +101,15 @@ ### 체스 게임 -- [x] 양팀의 킹이 생존 여부를 확인한다. - - [x] 킹이 죽으면 게임을 종료한다. -- [x] 게임 점수를 계산한다. +- 게임이 시작될 때 체스판을 만든다. + - DB에 저장된 데이터가 존재하면 불러온다. + - DB에 저장된 데이터가 없으면 체스판을 새로 만든다. +- 체스 게임을 진행한다. +- 게임 점수를 계산한다. +- 게임을 종료하면 데이터를 갱신한다. + - 킹이 죽지 않았으면 현재 체스판 데이터를 모두 저장한다. + - 킹이 죽으면 모든 테이터를 삭제한다. + ### 점수 계산 @@ -127,15 +133,12 @@ - [ ] 게임을 종료한다. - [ ] 체스판을 출력한다. - [ ] 각 팀의 점수를 출력한다. -- (추가) 킹이 죽으면 게임은 자동으로 종료된다. - -### 체스 게임 상태 저장 - -- [x] 게임이 시작될 때 체스판을 만든다. - - [x] DB에 저장된 데이터가 존재하면 불러온다. - - [x] DB에 저장된 데이터가 없으면 체스판을 새로 만든다. -- [x] 게임이 종료되면 기존 데이터를 모두 삭제한다. -- [ ] 킹이 죽지 않았으면 현재 체스판 데이터를 모두 저장한다. -- [ ] 킹이 죽으면 모든 테이터를 삭제한다. - - [ ] 보드 데이터 삭제 - - [ ] 턴 데이터 삭제 +- (추가) 킹이 죽으면 게임은 자동으로 종료된다. + +### DB CRUD 기능 + +- [ ] 기존 게임 데이터가 존재하는지 여부 조회 +- [ ] 기존 게임 데이터를 불러오기 +- [ ] 게임 데이터 갱신 + - [ ] 이전 게임 데이터 삭제 + - [ ] 현재 게임 데이터 저장 (피스들, 턴) From 68e36b823a52b4dbcb7e6afd9a9229b2b81599f7 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 21:43:41 +0900 Subject: [PATCH 26/94] =?UTF-8?q?rename:=20db,=20dao,=20dto=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/ChessController.java | 6 +++--- src/main/java/{domain/dao => db}/ConnectionManager.java | 2 +- src/main/java/{domain/dao => db}/PieceDao.java | 4 +++- src/main/java/{domain/dao => db}/TurnDao.java | 2 +- src/main/java/domain/board/ChessBoardFactory.java | 2 +- src/main/java/domain/{dao => dto}/PieceDto.java | 2 +- src/test/java/{domain/dao => db}/ConnectionManagerTest.java | 2 +- src/test/java/{domain/dao => db}/PieceDaoTest.java | 3 ++- src/test/java/{domain/dao => db}/TurnDaoTest.java | 2 +- src/test/java/domain/{dao => dto}/PieceDtoTest.java | 2 +- 10 files changed, 15 insertions(+), 12 deletions(-) rename src/main/java/{domain/dao => db}/ConnectionManager.java (97%) rename src/main/java/{domain/dao => db}/PieceDao.java (98%) rename src/main/java/{domain/dao => db}/TurnDao.java (98%) rename src/main/java/domain/{dao => dto}/PieceDto.java (97%) rename src/test/java/{domain/dao => db}/ConnectionManagerTest.java (96%) rename src/test/java/{domain/dao => db}/PieceDaoTest.java (97%) rename src/test/java/{domain/dao => db}/TurnDaoTest.java (94%) rename src/test/java/domain/{dao => dto}/PieceDtoTest.java (99%) diff --git a/src/main/java/controller/ChessController.java b/src/main/java/controller/ChessController.java index 98874af9869..bed02965d1a 100644 --- a/src/main/java/controller/ChessController.java +++ b/src/main/java/controller/ChessController.java @@ -2,11 +2,11 @@ import controller.command.Command; import controller.command.EndOnCommand; +import db.PieceDao; +import db.TurnDao; import domain.board.ChessBoard; import domain.board.ChessBoardFactory; -import domain.dao.PieceDao; -import domain.dao.PieceDto; -import domain.dao.TurnDao; +import domain.dto.PieceDto; import domain.piece.Color; import domain.piece.Piece; import domain.position.Position; diff --git a/src/main/java/domain/dao/ConnectionManager.java b/src/main/java/db/ConnectionManager.java similarity index 97% rename from src/main/java/domain/dao/ConnectionManager.java rename to src/main/java/db/ConnectionManager.java index 80429ad79e2..3c4c9b83e27 100644 --- a/src/main/java/domain/dao/ConnectionManager.java +++ b/src/main/java/db/ConnectionManager.java @@ -1,4 +1,4 @@ -package domain.dao; +package db; import java.sql.Connection; import java.sql.DriverManager; diff --git a/src/main/java/domain/dao/PieceDao.java b/src/main/java/db/PieceDao.java similarity index 98% rename from src/main/java/domain/dao/PieceDao.java rename to src/main/java/db/PieceDao.java index 23967b83e1a..98cb5d2b593 100644 --- a/src/main/java/domain/dao/PieceDao.java +++ b/src/main/java/db/PieceDao.java @@ -1,4 +1,6 @@ -package domain.dao; +package db; + +import domain.dto.PieceDto; import java.sql.Connection; import java.sql.PreparedStatement; diff --git a/src/main/java/domain/dao/TurnDao.java b/src/main/java/db/TurnDao.java similarity index 98% rename from src/main/java/domain/dao/TurnDao.java rename to src/main/java/db/TurnDao.java index 4653f6d11ff..11e07bc5b8e 100644 --- a/src/main/java/domain/dao/TurnDao.java +++ b/src/main/java/db/TurnDao.java @@ -1,4 +1,4 @@ -package domain.dao; +package db; import java.sql.Connection; import java.sql.PreparedStatement; diff --git a/src/main/java/domain/board/ChessBoardFactory.java b/src/main/java/domain/board/ChessBoardFactory.java index 0a792737cf5..352ec4f21f2 100644 --- a/src/main/java/domain/board/ChessBoardFactory.java +++ b/src/main/java/domain/board/ChessBoardFactory.java @@ -1,6 +1,6 @@ package domain.board; -import domain.dao.PieceDto; +import domain.dto.PieceDto; import domain.piece.Color; import domain.piece.Piece; import domain.piece.nonpawn.Bishop; diff --git a/src/main/java/domain/dao/PieceDto.java b/src/main/java/domain/dto/PieceDto.java similarity index 97% rename from src/main/java/domain/dao/PieceDto.java rename to src/main/java/domain/dto/PieceDto.java index d27da32feb1..52a3af1ed42 100644 --- a/src/main/java/domain/dao/PieceDto.java +++ b/src/main/java/domain/dto/PieceDto.java @@ -1,4 +1,4 @@ -package domain.dao; +package domain.dto; import domain.piece.Color; import domain.piece.Piece; diff --git a/src/test/java/domain/dao/ConnectionManagerTest.java b/src/test/java/db/ConnectionManagerTest.java similarity index 96% rename from src/test/java/domain/dao/ConnectionManagerTest.java rename to src/test/java/db/ConnectionManagerTest.java index 52598a47ca3..4e76043447f 100644 --- a/src/test/java/domain/dao/ConnectionManagerTest.java +++ b/src/test/java/db/ConnectionManagerTest.java @@ -1,4 +1,4 @@ -package domain.dao; +package db; import org.junit.jupiter.api.Test; diff --git a/src/test/java/domain/dao/PieceDaoTest.java b/src/test/java/db/PieceDaoTest.java similarity index 97% rename from src/test/java/domain/dao/PieceDaoTest.java rename to src/test/java/db/PieceDaoTest.java index 624ebee8655..33c422ff99f 100644 --- a/src/test/java/domain/dao/PieceDaoTest.java +++ b/src/test/java/db/PieceDaoTest.java @@ -1,5 +1,6 @@ -package domain.dao; +package db; +import domain.dto.PieceDto; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; diff --git a/src/test/java/domain/dao/TurnDaoTest.java b/src/test/java/db/TurnDaoTest.java similarity index 94% rename from src/test/java/domain/dao/TurnDaoTest.java rename to src/test/java/db/TurnDaoTest.java index f1fa722f9e9..9a1c6fa54f4 100644 --- a/src/test/java/domain/dao/TurnDaoTest.java +++ b/src/test/java/db/TurnDaoTest.java @@ -1,4 +1,4 @@ -package domain.dao; +package db; import domain.piece.Color; import org.junit.jupiter.api.Test; diff --git a/src/test/java/domain/dao/PieceDtoTest.java b/src/test/java/domain/dto/PieceDtoTest.java similarity index 99% rename from src/test/java/domain/dao/PieceDtoTest.java rename to src/test/java/domain/dto/PieceDtoTest.java index 5a187a9472d..d569dd03294 100644 --- a/src/test/java/domain/dao/PieceDtoTest.java +++ b/src/test/java/domain/dto/PieceDtoTest.java @@ -1,4 +1,4 @@ -package domain.dao; +package domain.dto; import domain.piece.Color; import domain.piece.Piece; From 56e689329f74b92eebea077bb4c0eb9bb1ece489 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 22:08:59 +0900 Subject: [PATCH 27/94] =?UTF-8?q?feat:=20DBService=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 ++--- src/main/java/db/DBService.java | 24 +++++++++++++ src/test/java/db/DBServiceTest.java | 56 +++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 4 deletions(-) create mode 100644 src/main/java/db/DBService.java create mode 100644 src/test/java/db/DBServiceTest.java diff --git a/README.md b/README.md index 84c44589b47..aa00fceff28 100644 --- a/README.md +++ b/README.md @@ -137,8 +137,8 @@ ### DB CRUD 기능 -- [ ] 기존 게임 데이터가 존재하는지 여부 조회 -- [ ] 기존 게임 데이터를 불러오기 -- [ ] 게임 데이터 갱신 +- [x] 기존 게임 데이터가 존재하는지 여부 조회 +- [x] 기존 게임 데이터를 불러오기 +- [ ] 게임 데이터 갱신 (피스들, 턴) - [ ] 이전 게임 데이터 삭제 - - [ ] 현재 게임 데이터 저장 (피스들, 턴) + - [ ] 현재 게임 데이터 저장 diff --git a/src/main/java/db/DBService.java b/src/main/java/db/DBService.java new file mode 100644 index 00000000000..f37b2ebf82d --- /dev/null +++ b/src/main/java/db/DBService.java @@ -0,0 +1,24 @@ +package db; + +import domain.dto.PieceDto; + +import java.util.List; + +public class DBService { + private final PieceDao pieceDao = new PieceDao(); + + public boolean doesPreviousDataExist() { + return pieceDao.count() != 0; + } + + public List loadPreviousData() { + return pieceDao.findAll(); + } + + public void updatePiece(final List pieceDtos) { + pieceDao.deleteAll(); + for (PieceDto pieceDto : pieceDtos) { + pieceDao.add(pieceDto); + } + } +} diff --git a/src/test/java/db/DBServiceTest.java b/src/test/java/db/DBServiceTest.java new file mode 100644 index 00000000000..2ee7487395b --- /dev/null +++ b/src/test/java/db/DBServiceTest.java @@ -0,0 +1,56 @@ +package db; + +import domain.dto.PieceDto; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class DBServiceTest { + private static final PieceDto A2WhitePawn = new PieceDto("A", "2", "WHITE", "PAWN"); + private static final PieceDto B2WhitePawn = new PieceDto("B", "2", "WHITE", "PAWN"); + private static final PieceDto C2WhitePawn = new PieceDto("C", "2", "WHITE", "PAWN"); + + private final PieceDao pieceDao = new PieceDao(); + private final DBService dbService = new DBService(); + + @BeforeEach + void setData() { + pieceDao.add(A2WhitePawn); + pieceDao.add(B2WhitePawn); + pieceDao.add(C2WhitePawn); + } + + @AfterEach + void rollback() { + pieceDao.deleteAll(); + } + + @Test + void 이전_게임_데이터가_존재한다() { + assertThat(dbService.doesPreviousDataExist()).isTrue(); + } + + @Test + void 이전_게임_데이터를_불러온다() { + assertThat(dbService.loadPreviousData()) + .containsExactlyInAnyOrder(A2WhitePawn, B2WhitePawn, C2WhitePawn); + } + + @Test + void 피스_데이터를_갱신한다() { + PieceDto A3WhitePawn = new PieceDto("A", "3", "WHITE", "PAWN"); + PieceDto B3WhitePawn = new PieceDto("B", "3", "WHITE", "PAWN"); + PieceDto C3WhitePawn = new PieceDto("C", "3", "WHITE", "PAWN"); + + List pieceDtos = List.of(A3WhitePawn, B3WhitePawn, C3WhitePawn); + + dbService.updatePiece(pieceDtos); + + assertThat(dbService.loadPreviousData()) + .containsExactlyInAnyOrder(A3WhitePawn, B3WhitePawn, C3WhitePawn); + } +} From ad3ec1149da93fc9a819807e86460ac999efe748 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 22:31:55 +0900 Subject: [PATCH 28/94] =?UTF-8?q?feat:=20=EC=9D=B4=EC=A0=84=20=ED=84=B4?= =?UTF-8?q?=EC=9D=84=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/db/DBService.java | 6 ++++++ src/main/java/db/PieceDao.java | 12 ++++++------ src/main/java/db/TurnDao.java | 22 +++++++++++++++++----- src/main/java/domain/dto/TurnDto.java | 9 +++++++++ src/test/java/db/DBServiceTest.java | 12 ++++++++++++ src/test/java/db/TurnDaoTest.java | 6 ++++-- 6 files changed, 54 insertions(+), 13 deletions(-) create mode 100644 src/main/java/domain/dto/TurnDto.java diff --git a/src/main/java/db/DBService.java b/src/main/java/db/DBService.java index f37b2ebf82d..a89be17b16c 100644 --- a/src/main/java/db/DBService.java +++ b/src/main/java/db/DBService.java @@ -1,11 +1,13 @@ package db; import domain.dto.PieceDto; +import domain.dto.TurnDto; import java.util.List; public class DBService { private final PieceDao pieceDao = new PieceDao(); + private final TurnDao turnDao = new TurnDao(); public boolean doesPreviousDataExist() { return pieceDao.count() != 0; @@ -15,6 +17,10 @@ public List loadPreviousData() { return pieceDao.findAll(); } + public TurnDto loadPreviousTurn() { + return turnDao.find(); + } + public void updatePiece(final List pieceDtos) { pieceDao.deleteAll(); for (PieceDto pieceDto : pieceDtos) { diff --git a/src/main/java/db/PieceDao.java b/src/main/java/db/PieceDao.java index 98cb5d2b593..062b7056338 100644 --- a/src/main/java/db/PieceDao.java +++ b/src/main/java/db/PieceDao.java @@ -17,11 +17,11 @@ private PieceDao(final ConnectionManager connectionManager) { this.connectionManager = connectionManager; } - public PieceDao() { + PieceDao() { this(new ConnectionManager()); } - public void add(final PieceDto piece) { + void add(final PieceDto piece) { final var query = "INSERT INTO " + tableName + " VALUES(?, ?, ?, ?)"; try (final var connection = connectionManager.getConnection(); final var preparedStatement = connection.prepareStatement(query)) { @@ -35,7 +35,7 @@ public void add(final PieceDto piece) { } } - public PieceDto find(final String file, final String rank) { + PieceDto find(final String file, final String rank) { final var query = "SELECT * FROM " + tableName + " WHERE board_file = ? and board_rank = ?"; try (final var connection = connectionManager.getConnection(); final var preparedStatement = connection.prepareStatement(query)) { @@ -55,7 +55,7 @@ public PieceDto find(final String file, final String rank) { return null; } - public List findAll() { + List findAll() { final List pieces = new ArrayList<>(); final String query = "SELECT * FROM " + tableName; try (final Connection connection = connectionManager.getConnection(); @@ -74,7 +74,7 @@ public List findAll() { return pieces; } - public void deleteAll() { + void deleteAll() { final var query = "DELETE FROM " + tableName; try (final var connection = connectionManager.getConnection(); final var preparedStatement = connection.prepareStatement(query)) { @@ -84,7 +84,7 @@ public void deleteAll() { } } - public int count() { + int count() { final var query = "SELECT COUNT(*) AS count FROM " + tableName; try (final var connection = connectionManager.getConnection(); final var preparedStatement = connection.prepareStatement(query)) { diff --git a/src/main/java/db/TurnDao.java b/src/main/java/db/TurnDao.java index 11e07bc5b8e..20ceb249f99 100644 --- a/src/main/java/db/TurnDao.java +++ b/src/main/java/db/TurnDao.java @@ -1,5 +1,7 @@ package db; +import domain.dto.TurnDto; + import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -13,17 +15,17 @@ private TurnDao(final ConnectionManager connectionManager) { this.connectionManager = connectionManager; } - public TurnDao() { + TurnDao() { this(new ConnectionManager()); } - public String find() { + TurnDto find() { final var query = "SELECT * FROM " + tableName; try (final var connection = connectionManager.getConnection(); final var prepareStatement = connection.prepareStatement(query)) { ResultSet resultSet = prepareStatement.executeQuery(); if (resultSet.next()) { - return resultSet.getString("color"); + return new TurnDto(resultSet.getString("color")); } } catch (SQLException e) { throw new RuntimeException(e); @@ -31,7 +33,7 @@ public String find() { return null; } - public void update(String color) { + void update(TurnDto turnDto) { final String deleteQuery = "DELETE FROM " + tableName; final String insertQuery = "INSERT INTO " + tableName + " (color) VALUES (?)"; try (final Connection connection = connectionManager.getConnection(); @@ -39,10 +41,20 @@ public void update(String color) { final PreparedStatement insertStatement = connection.prepareStatement(insertQuery)) { deleteStatement.executeUpdate(); - insertStatement.setString(1, color); + insertStatement.setString(1, turnDto.color()); insertStatement.executeUpdate(); } catch (SQLException e) { throw new RuntimeException(e); } } + + public void deleteAll() { + final String deleteQuery = "DELETE FROM " + tableName; + try (final Connection connection = connectionManager.getConnection(); + final PreparedStatement deleteStatement = connection.prepareStatement(deleteQuery)) { + deleteStatement.executeUpdate(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } } diff --git a/src/main/java/domain/dto/TurnDto.java b/src/main/java/domain/dto/TurnDto.java new file mode 100644 index 00000000000..874c4d86ff0 --- /dev/null +++ b/src/main/java/domain/dto/TurnDto.java @@ -0,0 +1,9 @@ +package domain.dto; + +import domain.piece.Color; + +public record TurnDto(String color) { + public Color getTurn() { + return Color.valueOf(color); + } +} diff --git a/src/test/java/db/DBServiceTest.java b/src/test/java/db/DBServiceTest.java index 2ee7487395b..249243a6c9c 100644 --- a/src/test/java/db/DBServiceTest.java +++ b/src/test/java/db/DBServiceTest.java @@ -1,6 +1,8 @@ package db; import domain.dto.PieceDto; +import domain.dto.TurnDto; +import domain.piece.Color; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -13,8 +15,10 @@ class DBServiceTest { private static final PieceDto A2WhitePawn = new PieceDto("A", "2", "WHITE", "PAWN"); private static final PieceDto B2WhitePawn = new PieceDto("B", "2", "WHITE", "PAWN"); private static final PieceDto C2WhitePawn = new PieceDto("C", "2", "WHITE", "PAWN"); + private static final TurnDto whiteTurn = new TurnDto("WHITE"); private final PieceDao pieceDao = new PieceDao(); + private final TurnDao turnDao = new TurnDao(); private final DBService dbService = new DBService(); @BeforeEach @@ -22,11 +26,13 @@ void setData() { pieceDao.add(A2WhitePawn); pieceDao.add(B2WhitePawn); pieceDao.add(C2WhitePawn); + turnDao.update(whiteTurn); } @AfterEach void rollback() { pieceDao.deleteAll(); + turnDao.deleteAll(); } @Test @@ -40,6 +46,12 @@ void rollback() { .containsExactlyInAnyOrder(A2WhitePawn, B2WhitePawn, C2WhitePawn); } + @Test + void 이전_게임의_턴_데이터를_불러온다() { + assertThat(dbService.loadPreviousTurn().getTurn()) + .isEqualTo(Color.WHITE); + } + @Test void 피스_데이터를_갱신한다() { PieceDto A3WhitePawn = new PieceDto("A", "3", "WHITE", "PAWN"); diff --git a/src/test/java/db/TurnDaoTest.java b/src/test/java/db/TurnDaoTest.java index 9a1c6fa54f4..bf5c3c241dc 100644 --- a/src/test/java/db/TurnDaoTest.java +++ b/src/test/java/db/TurnDaoTest.java @@ -1,5 +1,6 @@ package db; +import domain.dto.TurnDto; import domain.piece.Color; import org.junit.jupiter.api.Test; @@ -8,10 +9,11 @@ class TurnDaoTest { @Test void 턴을_저장한다() { + TurnDto whiteTurn = new TurnDto("WHITE"); TurnDao turnDao = new TurnDao(); - turnDao.update(Color.WHITE.name()); + turnDao.update(whiteTurn); - assertThat(turnDao.find()).isEqualTo("WHITE"); + assertThat(turnDao.find().getTurn()).isEqualTo(Color.WHITE); } } From 7c04c5d2442bd5df65087cf6cde30cae6e1edbdf Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 22:39:27 +0900 Subject: [PATCH 29/94] =?UTF-8?q?feat:=20=ED=84=B4=EC=9D=84=20=EA=B0=B1?= =?UTF-8?q?=EC=8B=A0=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- src/main/java/db/DBService.java | 5 +++++ src/test/java/db/DBServiceTest.java | 9 +++++++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index aa00fceff28..b7e67d729b5 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,6 @@ - [x] 기존 게임 데이터가 존재하는지 여부 조회 - [x] 기존 게임 데이터를 불러오기 -- [ ] 게임 데이터 갱신 (피스들, 턴) - - [ ] 이전 게임 데이터 삭제 - - [ ] 현재 게임 데이터 저장 +- [x] 게임 데이터 갱신 (피스들, 턴) + - [x] 이전 게임 데이터 삭제 + - [x] 현재 게임 데이터 저장 diff --git a/src/main/java/db/DBService.java b/src/main/java/db/DBService.java index a89be17b16c..b7e8aba1ed2 100644 --- a/src/main/java/db/DBService.java +++ b/src/main/java/db/DBService.java @@ -27,4 +27,9 @@ public void updatePiece(final List pieceDtos) { pieceDao.add(pieceDto); } } + + public void updateTurn(final TurnDto turnDto) { + turnDao.deleteAll(); + turnDao.update(turnDto); + } } diff --git a/src/test/java/db/DBServiceTest.java b/src/test/java/db/DBServiceTest.java index 249243a6c9c..0c61b2c7d32 100644 --- a/src/test/java/db/DBServiceTest.java +++ b/src/test/java/db/DBServiceTest.java @@ -65,4 +65,13 @@ void rollback() { assertThat(dbService.loadPreviousData()) .containsExactlyInAnyOrder(A3WhitePawn, B3WhitePawn, C3WhitePawn); } + + @Test + void 턴_데이터를_갱신한다() { + TurnDto blackTurn = new TurnDto("BLACK"); + + dbService.updateTurn(blackTurn); + + assertThat(dbService.loadPreviousTurn().getTurn()).isEqualTo(Color.BLACK); + } } From 740d045f5b87bb753310020651132d4189c2e6be Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 22:52:36 +0900 Subject: [PATCH 30/94] =?UTF-8?q?refactor:=20Controller=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/ChessController.java | 34 ++++++++----------- src/main/java/domain/board/ChessBoard.java | 13 +++++-- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/main/java/controller/ChessController.java b/src/main/java/controller/ChessController.java index bed02965d1a..c4b8f99dfa9 100644 --- a/src/main/java/controller/ChessController.java +++ b/src/main/java/controller/ChessController.java @@ -2,14 +2,10 @@ import controller.command.Command; import controller.command.EndOnCommand; -import db.PieceDao; -import db.TurnDao; +import db.DBService; import domain.board.ChessBoard; import domain.board.ChessBoardFactory; -import domain.dto.PieceDto; -import domain.piece.Color; -import domain.piece.Piece; -import domain.position.Position; +import domain.dto.TurnDto; import view.InputView; import view.OutputView; @@ -23,11 +19,10 @@ public ChessController(InputView inputView, OutputView outputView) { } public void start() { - PieceDao pieceDao = new PieceDao(); - TurnDao turnDao = new TurnDao(); + DBService dbService = new DBService(); outputView.printGameGuideMessage(); - final ChessBoard board = createChessBoard(pieceDao, turnDao); + final ChessBoard board = createChessBoard(dbService); Command command = readStartCommandUntilValid(); while (command.isNotEnded()) { @@ -35,19 +30,13 @@ public void start() { command = readCommandIfGameNotEnded(board); } - pieceDao.deleteAll(); - for (var positionAndPiece : board.getBoard().entrySet()) { - Position position = positionAndPiece.getKey(); - Piece piece = positionAndPiece.getValue(); - pieceDao.add(PieceDto.of(position, piece)); - } - turnDao.update(board.getTurn().name()); + updateGameStatus(dbService, board); } - private ChessBoard createChessBoard(PieceDao pieceDao, TurnDao turnDao) { - if (pieceDao.count() != 0) { - String color = turnDao.find(); - return ChessBoardFactory.loadPreviousChessBoard(pieceDao.findAll(), Color.valueOf(color)); + private ChessBoard createChessBoard(DBService dbService) { + if (dbService.doesPreviousDataExist()) { + TurnDto turnDto = dbService.loadPreviousTurn(); + return ChessBoardFactory.loadPreviousChessBoard(dbService.loadPreviousData(), turnDto.getTurn()); } return ChessBoardFactory.createInitialChessBoard(); } @@ -76,4 +65,9 @@ private Command readCommandUntilValid() { return readCommandUntilValid(); } } + + private static void updateGameStatus(final DBService dbService, final ChessBoard board) { + dbService.updatePiece(board.getPieces()); + dbService.updateTurn(board.getTurn()); + } } diff --git a/src/main/java/domain/board/ChessBoard.java b/src/main/java/domain/board/ChessBoard.java index cd8684e0a02..246e75b504d 100644 --- a/src/main/java/domain/board/ChessBoard.java +++ b/src/main/java/domain/board/ChessBoard.java @@ -1,5 +1,7 @@ package domain.board; +import domain.dto.PieceDto; +import domain.dto.TurnDto; import domain.piece.Color; import domain.piece.Empty; import domain.piece.Piece; @@ -9,6 +11,7 @@ import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; public class ChessBoard { @@ -91,7 +94,13 @@ public Map getBoard() { return Collections.unmodifiableMap(board); } - public Color getTurn() { - return this.turn; + public List getPieces() { + return board.entrySet().stream() + .map(entry -> PieceDto.of(entry.getKey(), entry.getValue())) + .toList(); + } + + public TurnDto getTurn() { + return new TurnDto(this.turn.name()); } } From 0e2db44bc51f9b2148705d84c3bedbb032556370 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 25 Mar 2024 23:07:48 +0900 Subject: [PATCH 31/94] =?UTF-8?q?feat:=20King=EC=9D=B4=20=EC=9E=A1?= =?UTF-8?q?=ED=9E=88=EB=A9=B4=20=EA=B2=8C=EC=9E=84=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=82=AD=EC=A0=9C=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/ChessController.java | 12 +++++++----- src/main/java/db/DBService.java | 5 +++++ src/test/java/db/DBServiceTest.java | 7 +++++++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/main/java/controller/ChessController.java b/src/main/java/controller/ChessController.java index c4b8f99dfa9..1857701478c 100644 --- a/src/main/java/controller/ChessController.java +++ b/src/main/java/controller/ChessController.java @@ -19,17 +19,15 @@ public ChessController(InputView inputView, OutputView outputView) { } public void start() { - DBService dbService = new DBService(); - outputView.printGameGuideMessage(); - final ChessBoard board = createChessBoard(dbService); + DBService dbService = new DBService(); + ChessBoard board = createChessBoard(dbService); Command command = readStartCommandUntilValid(); while (command.isNotEnded()) { command.execute(board, outputView); command = readCommandIfGameNotEnded(board); } - updateGameStatus(dbService, board); } @@ -66,7 +64,11 @@ private Command readCommandUntilValid() { } } - private static void updateGameStatus(final DBService dbService, final ChessBoard board) { + private void updateGameStatus(final DBService dbService, final ChessBoard board) { + if (board.isKingNotExist()) { + dbService.deletePreviousData(); + return; + } dbService.updatePiece(board.getPieces()); dbService.updateTurn(board.getTurn()); } diff --git a/src/main/java/db/DBService.java b/src/main/java/db/DBService.java index b7e8aba1ed2..5b7ca8c9514 100644 --- a/src/main/java/db/DBService.java +++ b/src/main/java/db/DBService.java @@ -32,4 +32,9 @@ public void updateTurn(final TurnDto turnDto) { turnDao.deleteAll(); turnDao.update(turnDto); } + + public void deletePreviousData() { + pieceDao.deleteAll(); + turnDao.deleteAll(); + } } diff --git a/src/test/java/db/DBServiceTest.java b/src/test/java/db/DBServiceTest.java index 0c61b2c7d32..88ac6d55bfd 100644 --- a/src/test/java/db/DBServiceTest.java +++ b/src/test/java/db/DBServiceTest.java @@ -74,4 +74,11 @@ void rollback() { assertThat(dbService.loadPreviousTurn().getTurn()).isEqualTo(Color.BLACK); } + + @Test + void 모든_데이터를_삭제한다() { + dbService.deletePreviousData(); + + assertThat(dbService.doesPreviousDataExist()).isFalse(); + } } From 345b08e1f491714ae1a135c762fed31ac9a80ae4 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Tue, 26 Mar 2024 11:47:31 +0900 Subject: [PATCH 32/94] =?UTF-8?q?refactor:=20=EC=BB=A4=EB=A7=A8=EB=93=9C?= =?UTF-8?q?=20=EA=B0=80=EA=B3=B5=ED=95=98=EB=8A=94=20=EC=B1=85=EC=9E=84?= =?UTF-8?q?=EC=9D=84=20InputView=EC=97=90=EC=84=9C=20CommandType=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=9C=84=EC=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/position/Position.java | 4 ++ src/main/java/view/Command.java | 17 ------- src/main/java/view/CommandType.java | 46 +++++++++++++++++++ src/main/java/view/InputView.java | 51 ++++++++++----------- src/main/java/view/MessageResolver.java | 6 +-- 5 files changed, 78 insertions(+), 46 deletions(-) delete mode 100644 src/main/java/view/Command.java create mode 100644 src/main/java/view/CommandType.java diff --git a/src/main/java/domain/position/Position.java b/src/main/java/domain/position/Position.java index ff3bae8458f..bef5259024b 100644 --- a/src/main/java/domain/position/Position.java +++ b/src/main/java/domain/position/Position.java @@ -15,6 +15,10 @@ public Position(final String file, final int rank) { this(File.fromName(file), Rank.fromNumber(rank)); } + public Position(final String fileAndRank) { + this(fileAndRank.substring(0, 1), Integer.parseInt(fileAndRank.substring(1))); + } + public boolean isStraightAt(final Position target) { validateSamePosition(target); return calculateFileGap(target) == 0 || calculateRankGap(target) == 0; diff --git a/src/main/java/view/Command.java b/src/main/java/view/Command.java deleted file mode 100644 index 8336742975f..00000000000 --- a/src/main/java/view/Command.java +++ /dev/null @@ -1,17 +0,0 @@ -package view; - -public enum Command { - START("start"), - END("end"), - MOVE("move"); - - private final String message; - - Command(String message) { - this.message = message; - } - - public String message() { - return message; - } -} diff --git a/src/main/java/view/CommandType.java b/src/main/java/view/CommandType.java new file mode 100644 index 00000000000..a807ec45171 --- /dev/null +++ b/src/main/java/view/CommandType.java @@ -0,0 +1,46 @@ +package view; + +import controller.command.Command; +import controller.command.EndOnCommand; +import controller.command.MoveOnCommand; +import controller.command.StartOnCommand; +import controller.command.StatusOnCommand; +import domain.position.Position; + +import java.util.Arrays; +import java.util.function.Function; + +public enum CommandType { + START(tokens -> isCommand(tokens, "START", 1), + (tokens) -> new StartOnCommand()), + END(tokens -> isCommand(tokens, "END", 1), + (tokens) -> new EndOnCommand()), + STATUS(tokens -> isCommand(tokens, "STATUS", 1), + (tokens) -> new StatusOnCommand()), + MOVE(tokens -> isCommand(tokens, "MOVE", 3), + (tokens) -> new MoveOnCommand(new Position(tokens[1]), new Position(tokens[2]))); + + private final Function validator; + private final Function command; + + CommandType(final Function validator, final Function command) { + this.validator = validator; + this.command = command; + } + + public static Command getCommand(String[] tokens) { + CommandType findCommand = Arrays.stream(CommandType.values()) + .filter(command -> command.validator.apply(tokens)) + .findFirst() + .orElseThrow(IllegalArgumentException::new); + return findCommand.command.apply(tokens); + } + + private static boolean isCommand(String[] tokens, String commandName, int size) { + return tokens.length == size && commandName.equals(tokens[0]); + } + + public String message() { + return name().toLowerCase(); + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 5b85506b943..42801c0df64 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,15 +1,14 @@ package view; import controller.command.Command; -import controller.command.EndOnCommand; -import controller.command.MoveOnCommand; import controller.command.StartOnCommand; -import controller.command.StatusOnCommand; -import domain.position.Position; import java.util.Scanner; public class InputView { + public static final String WRONG_COMMAND_ERROR_MESSAGE = "잘못된 형식의 명령어입니다."; + public static final String GAME_NOT_STARTED_ERROR_MESSAGE = "먼저, 게임을 시작해 주세요."; + private final Scanner scanner; public InputView() { @@ -17,41 +16,41 @@ public InputView() { } public Command readStartCommand() { - String[] rawInput = scanner.nextLine().trim().split(" "); - if (hasSize(rawInput, 1) && "start".equals(rawInput[0])) { + String[] tokens = readUserInput(); + if (tokens.length == 1 && CommandType.START.message().equals(tokens[0])) { return new StartOnCommand(); } - throw new IllegalArgumentException("먼저, 게임을 시작해 주세요."); + throw new IllegalArgumentException(GAME_NOT_STARTED_ERROR_MESSAGE); } public Command readCommand() { - String[] rawInput = scanner.nextLine().trim().split(" "); - if (hasSize(rawInput, 1) && "start".equals(rawInput[0])) { - return new StartOnCommand(); - } - if (hasSize(rawInput, 1) && "status".equals(rawInput[0])) { - return new StatusOnCommand(); - } - if (hasSize(rawInput, 3) && "move".equals(rawInput[0])) { - return new MoveOnCommand(resolvePosition(rawInput[1]), resolvePosition(rawInput[2])); + String[] tokens = readUserInput(); + try { + validateCommand(tokens); + return CommandType.getCommand(tokens); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException(WRONG_COMMAND_ERROR_MESSAGE); } - if (hasSize(rawInput, 1) && "end".equals(rawInput[0])) { - return new EndOnCommand(); + } + + private void validateCommand(String[] tokens) { + for (int i = 1; i < tokens.length; i++) { + validatePositionFormat(tokens[i]); } - throw new IllegalArgumentException("잘못된 형식의 명령어입니다."); } - private Position resolvePosition(String position) { - String file = position.substring(0, 1).toUpperCase(); - String rank = position.substring(1); + private void validatePositionFormat(String token) { + if (token.length() != 2) { + throw new IllegalArgumentException(); + } try { - return new Position(file, Integer.parseInt(rank)); + Integer.parseInt(token.substring(1)); } catch (NumberFormatException e) { - throw new IllegalArgumentException("잘못된 형식의 명령어입니다."); + throw new IllegalArgumentException(); } } - private boolean hasSize(final String[] rawInput, int size) { - return rawInput.length == size; + private String[] readUserInput() { + return scanner.nextLine().trim().toUpperCase().split(" "); } } diff --git a/src/main/java/view/MessageResolver.java b/src/main/java/view/MessageResolver.java index af585a7dc49..a1f0bd024b0 100644 --- a/src/main/java/view/MessageResolver.java +++ b/src/main/java/view/MessageResolver.java @@ -14,9 +14,9 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; -import static view.Command.END; -import static view.Command.MOVE; -import static view.Command.START; +import static view.CommandType.END; +import static view.CommandType.MOVE; +import static view.CommandType.START; public class MessageResolver { public static final int BOARD_LENGTH = 8; From b4054457a70cc6e1b6943a3fcc52bc4bc65eb93b Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Tue, 26 Mar 2024 12:08:35 +0900 Subject: [PATCH 33/94] =?UTF-8?q?refactor:=20DB=20table=EB=AA=85=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/{ => sql}/pieces.sql | 0 src/main/resources/{ => sql}/turns.sql | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/main/resources/{ => sql}/pieces.sql (100%) rename src/main/resources/{ => sql}/turns.sql (100%) diff --git a/src/main/resources/pieces.sql b/src/main/resources/sql/pieces.sql similarity index 100% rename from src/main/resources/pieces.sql rename to src/main/resources/sql/pieces.sql diff --git a/src/main/resources/turns.sql b/src/main/resources/sql/turns.sql similarity index 100% rename from src/main/resources/turns.sql rename to src/main/resources/sql/turns.sql From 5c46b6d686d51b16f853ef910d943b290396a1d5 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Tue, 26 Mar 2024 12:13:30 +0900 Subject: [PATCH 34/94] =?UTF-8?q?feat:=20=EA=B2=8C=EC=9E=84=EC=9D=B4=20?= =?UTF-8?q?=EC=A2=85=EB=A3=8C=EB=90=98=EB=A9=B4=20=EC=A0=90=EC=88=98?= =?UTF-8?q?=EB=A5=BC=20=EC=B6=9C=EB=A0=A5=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 ++--- src/main/java/controller/command/EndOnCommand.java | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b7e67d729b5..4af28f6c9ef 100644 --- a/README.md +++ b/README.md @@ -130,9 +130,8 @@ - status - [x] 각 팀의 점수를 출력한다. - end - - [ ] 게임을 종료한다. - - [ ] 체스판을 출력한다. - - [ ] 각 팀의 점수를 출력한다. + - [x] 게임을 종료한다. + - [x] 각 팀의 점수를 출력한다. - (추가) 킹이 죽으면 게임은 자동으로 종료된다. ### DB CRUD 기능 diff --git a/src/main/java/controller/command/EndOnCommand.java b/src/main/java/controller/command/EndOnCommand.java index 3633dddd555..d4c83efd282 100644 --- a/src/main/java/controller/command/EndOnCommand.java +++ b/src/main/java/controller/command/EndOnCommand.java @@ -6,7 +6,7 @@ public class EndOnCommand implements Command { @Override public void execute(final ChessBoard board, final OutputView outputView) { - + outputView.printScore(board.calculateScore()); } @Override From 50ad35c00f20e2cb6216826afb7a6d503dd7f159 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Tue, 26 Mar 2024 12:13:47 +0900 Subject: [PATCH 35/94] =?UTF-8?q?refactor:=20=EC=BB=A8=ED=8A=B8=EB=A1=A4?= =?UTF-8?q?=EB=9F=AC=20=EA=B5=AC=EC=A1=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/ChessController.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/controller/ChessController.java b/src/main/java/controller/ChessController.java index 1857701478c..7ddda12c1eb 100644 --- a/src/main/java/controller/ChessController.java +++ b/src/main/java/controller/ChessController.java @@ -19,15 +19,16 @@ public ChessController(InputView inputView, OutputView outputView) { } public void start() { - outputView.printGameGuideMessage(); - DBService dbService = new DBService(); ChessBoard board = createChessBoard(dbService); + + outputView.printGameGuideMessage(); Command command = readStartCommandUntilValid(); while (command.isNotEnded()) { command.execute(board, outputView); - command = readCommandIfGameNotEnded(board); + command = readNextCommand(board); } + command.execute(board, outputView); updateGameStatus(dbService, board); } @@ -48,7 +49,7 @@ private Command readStartCommandUntilValid() { } } - private Command readCommandIfGameNotEnded(final ChessBoard board) { + private Command readNextCommand(final ChessBoard board) { if (board.isKingNotExist()) { return new EndOnCommand(); } From ddbfe11dd74ba17047c4116dbdc9a567d112eaaf Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Tue, 26 Mar 2024 14:03:50 +0900 Subject: [PATCH 36/94] =?UTF-8?q?fix:=20=EA=B2=8C=EC=9E=84=20=EC=8B=9C?= =?UTF-8?q?=EC=9E=91=20=EC=95=88=EB=90=98=EB=8A=94=20=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/InputView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 42801c0df64..19f9e183246 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -17,7 +17,7 @@ public InputView() { public Command readStartCommand() { String[] tokens = readUserInput(); - if (tokens.length == 1 && CommandType.START.message().equals(tokens[0])) { + if (tokens.length == 1 && CommandType.START.name().equals(tokens[0])) { return new StartOnCommand(); } throw new IllegalArgumentException(GAME_NOT_STARTED_ERROR_MESSAGE); From 657dd4cd1e85d2d71121a90664d9ddd29c10c74c Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Wed, 27 Mar 2024 13:19:25 +0900 Subject: [PATCH 37/94] =?UTF-8?q?refactor:=20JDBC=20=EC=A4=91=EB=B3=B5=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/ChessController.java | 2 +- src/main/java/db/DBService.java | 4 +- src/main/java/db/JdbcTemplate.java | 65 +++++++++++ src/main/java/db/PieceDao.java | 103 +++++------------- src/main/java/db/RowMapper.java | 9 ++ src/main/java/db/TurnDao.java | 63 ++++------- src/test/java/db/DBServiceTest.java | 4 +- src/test/java/db/PieceDaoTest.java | 6 +- 8 files changed, 134 insertions(+), 122 deletions(-) create mode 100644 src/main/java/db/JdbcTemplate.java create mode 100644 src/main/java/db/RowMapper.java diff --git a/src/main/java/controller/ChessController.java b/src/main/java/controller/ChessController.java index 7ddda12c1eb..b90784e88a9 100644 --- a/src/main/java/controller/ChessController.java +++ b/src/main/java/controller/ChessController.java @@ -33,7 +33,7 @@ public void start() { } private ChessBoard createChessBoard(DBService dbService) { - if (dbService.doesPreviousDataExist()) { + if (dbService.isPreviousDataExist()) { TurnDto turnDto = dbService.loadPreviousTurn(); return ChessBoardFactory.loadPreviousChessBoard(dbService.loadPreviousData(), turnDto.getTurn()); } diff --git a/src/main/java/db/DBService.java b/src/main/java/db/DBService.java index 5b7ca8c9514..15cc8827a10 100644 --- a/src/main/java/db/DBService.java +++ b/src/main/java/db/DBService.java @@ -9,8 +9,8 @@ public class DBService { private final PieceDao pieceDao = new PieceDao(); private final TurnDao turnDao = new TurnDao(); - public boolean doesPreviousDataExist() { - return pieceDao.count() != 0; + public boolean isPreviousDataExist() { + return pieceDao.hasRecords(); } public List loadPreviousData() { diff --git a/src/main/java/db/JdbcTemplate.java b/src/main/java/db/JdbcTemplate.java new file mode 100644 index 00000000000..8062983d517 --- /dev/null +++ b/src/main/java/db/JdbcTemplate.java @@ -0,0 +1,65 @@ +package db; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +public class JdbcTemplate { + private final ConnectionManager connectionManager; + + public JdbcTemplate() { + this.connectionManager = new ConnectionManager(); + } + + void add(final String query, final String... parameters) { + execute(query, parameters); + } + + public List find(final String query, final RowMapper mapper, final String... parameters) { + return executeAndGet(query, mapper, parameters); + } + + public void delete(final String query, final String... parameters) { + execute(query, parameters); + } + + private void execute(final String query, final String[] parameters) { + try (final var connection = connectionManager.getConnection(); + final var preparedStatement = connection.prepareStatement(query)) { + setParameters(preparedStatement, parameters); + preparedStatement.executeUpdate(); + } catch (final SQLException e) { + throw new IllegalArgumentException(e.getMessage()); + } + } + + private List executeAndGet(final String query, final RowMapper mapper, final String[] parameters) { + try (final var connection = connectionManager.getConnection(); + final var preparedStatement = connection.prepareStatement(query)) { + setParameters(preparedStatement, parameters); + return resolveResult(mapper, preparedStatement); + } catch (final SQLException e) { + throw new IllegalArgumentException(e.getMessage()); + } + } + + private void setParameters(final PreparedStatement preparedStatement, final String... parameters) throws SQLException { + for (int i = 0; i < parameters.length; i++) { + preparedStatement.setString(i + 1, parameters[i]); + } + } + + private List resolveResult(final RowMapper mapper, final PreparedStatement preparedStatement) { + try (final ResultSet resultSet = preparedStatement.executeQuery()) { + final List results = new ArrayList<>(); + while (resultSet.next()) { + results.add(mapper.mapRow(resultSet)); + } + return results; + } catch (final SQLException e) { + throw new IllegalArgumentException(e.getMessage()); + } + } +} diff --git a/src/main/java/db/PieceDao.java b/src/main/java/db/PieceDao.java index 062b7056338..a38b0708816 100644 --- a/src/main/java/db/PieceDao.java +++ b/src/main/java/db/PieceDao.java @@ -2,99 +2,54 @@ import domain.dto.PieceDto; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; import java.util.List; public class PieceDao { - private static final String tableName = "pieces"; - private final ConnectionManager connectionManager; + private static final String TABLE_NAME = "pieces"; - private PieceDao(final ConnectionManager connectionManager) { - this.connectionManager = connectionManager; - } + private final JdbcTemplate jdbcTemplate; + private final RowMapper rowMapper = (resultSet) -> new PieceDto( + resultSet.getString("board_file"), + resultSet.getString("board_rank"), + resultSet.getString("color"), + resultSet.getString("type") + ); PieceDao() { - this(new ConnectionManager()); + this(new JdbcTemplate()); + } + + private PieceDao(final JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; } void add(final PieceDto piece) { - final var query = "INSERT INTO " + tableName + " VALUES(?, ?, ?, ?)"; - try (final var connection = connectionManager.getConnection(); - final var preparedStatement = connection.prepareStatement(query)) { - preparedStatement.setString(1, piece.boardFile()); - preparedStatement.setString(2, piece.boardRank()); - preparedStatement.setString(3, piece.color()); - preparedStatement.setString(4, piece.type()); - preparedStatement.executeUpdate(); - } catch (final SQLException e) { - throw new RuntimeException(e); - } + final String query = "INSERT INTO " + TABLE_NAME + " VALUES(?, ?, ?, ?)"; + jdbcTemplate.add(query, piece.boardFile(), piece.boardRank(), piece.color(), piece.type()); } - PieceDto find(final String file, final String rank) { - final var query = "SELECT * FROM " + tableName + " WHERE board_file = ? and board_rank = ?"; - try (final var connection = connectionManager.getConnection(); - final var preparedStatement = connection.prepareStatement(query)) { - preparedStatement.setString(1, file); - preparedStatement.setString(2, rank); - final ResultSet resultSet = preparedStatement.executeQuery(); - if (resultSet.next()) { - return new PieceDto(file, - rank, - resultSet.getString("color"), - resultSet.getString("type") - ); - } - } catch (final SQLException e) { - throw new RuntimeException(e); + PieceDto findOne(final String file, final String rank) { + final String query = "SELECT * FROM " + TABLE_NAME + " WHERE board_file = ? and board_rank = ? limit 1"; + final List pieces = jdbcTemplate.find(query, rowMapper, file, rank); + if (pieces.size() == 0) { + throw new IllegalArgumentException("데이터가 없습니다."); } - return null; + return pieces.get(0); } List findAll() { - final List pieces = new ArrayList<>(); - final String query = "SELECT * FROM " + tableName; - try (final Connection connection = connectionManager.getConnection(); - final PreparedStatement preparedStatement = connection.prepareStatement(query)) { - final ResultSet resultSet = preparedStatement.executeQuery(); - while (resultSet.next()) { - String file = resultSet.getString("board_file"); - String rank = resultSet.getString("board_rank"); - String color = resultSet.getString("color"); - String type = resultSet.getString("type"); - pieces.add(new PieceDto(file, rank, color, type)); - } - } catch (final SQLException e) { - throw new RuntimeException(e); - } - return pieces; + final String query = "SELECT * FROM " + TABLE_NAME; + return jdbcTemplate.find(query, rowMapper); } void deleteAll() { - final var query = "DELETE FROM " + tableName; - try (final var connection = connectionManager.getConnection(); - final var preparedStatement = connection.prepareStatement(query)) { - preparedStatement.executeUpdate(); - } catch (SQLException e) { - throw new RuntimeException(e); - } + final String query = "DELETE FROM " + TABLE_NAME; + jdbcTemplate.delete(query); } - int count() { - final var query = "SELECT COUNT(*) AS count FROM " + tableName; - try (final var connection = connectionManager.getConnection(); - final var preparedStatement = connection.prepareStatement(query)) { - ResultSet resultSet = preparedStatement.executeQuery(); - if (resultSet.next()) { - return Integer.parseInt(resultSet.getString("count")); - } - } catch (SQLException e) { - throw new RuntimeException(e); - } - return 0; + boolean hasRecords() { + final String query = "SELECT * FROM " + TABLE_NAME + " LIMIT 1"; + final List pieces = jdbcTemplate.find(query, rowMapper); + return pieces.size() != 0; } } diff --git a/src/main/java/db/RowMapper.java b/src/main/java/db/RowMapper.java new file mode 100644 index 00000000000..3d7b868fb58 --- /dev/null +++ b/src/main/java/db/RowMapper.java @@ -0,0 +1,9 @@ +package db; + +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/db/TurnDao.java b/src/main/java/db/TurnDao.java index 20ceb249f99..ec0aeaa38be 100644 --- a/src/main/java/db/TurnDao.java +++ b/src/main/java/db/TurnDao.java @@ -2,59 +2,42 @@ import domain.dto.TurnDto; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; +import java.util.List; public class TurnDao { - private static final String tableName = "turns"; - private final ConnectionManager connectionManager; + private static final String TABLE_NAME = "turns"; - private TurnDao(final ConnectionManager connectionManager) { - this.connectionManager = connectionManager; - } + private final JdbcTemplate jdbcTemplate; + private final RowMapper rowMapper = (resultSet) -> + new TurnDto(resultSet.getString("color")); TurnDao() { - this(new ConnectionManager()); + this(new JdbcTemplate()); + } + + private TurnDao(final JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; } TurnDto find() { - final var query = "SELECT * FROM " + tableName; - try (final var connection = connectionManager.getConnection(); - final var prepareStatement = connection.prepareStatement(query)) { - ResultSet resultSet = prepareStatement.executeQuery(); - if (resultSet.next()) { - return new TurnDto(resultSet.getString("color")); - } - } catch (SQLException e) { - throw new RuntimeException(e); + final var query = "SELECT * FROM " + TABLE_NAME + " LIMIT 1"; + final List turns = jdbcTemplate.find(query, rowMapper); + if (turns.isEmpty()) { + throw new IllegalArgumentException("데이터가 없습니다."); } - return null; + return turns.get(0); } - void update(TurnDto turnDto) { - final String deleteQuery = "DELETE FROM " + tableName; - final String insertQuery = "INSERT INTO " + tableName + " (color) VALUES (?)"; - try (final Connection connection = connectionManager.getConnection(); - final PreparedStatement deleteStatement = connection.prepareStatement(deleteQuery); - final PreparedStatement insertStatement = connection.prepareStatement(insertQuery)) { - deleteStatement.executeUpdate(); - - insertStatement.setString(1, turnDto.color()); - insertStatement.executeUpdate(); - } catch (SQLException e) { - throw new RuntimeException(e); - } + + void update(final TurnDto turnDto) { + final String deleteQuery = "DELETE FROM " + TABLE_NAME; + final String insertQuery = "INSERT INTO " + TABLE_NAME + " (color) VALUES (?)"; + jdbcTemplate.delete(deleteQuery); + jdbcTemplate.add(insertQuery, turnDto.color()); } public void deleteAll() { - final String deleteQuery = "DELETE FROM " + tableName; - try (final Connection connection = connectionManager.getConnection(); - final PreparedStatement deleteStatement = connection.prepareStatement(deleteQuery)) { - deleteStatement.executeUpdate(); - } catch (SQLException e) { - throw new RuntimeException(e); - } + final String query = "DELETE FROM " + TABLE_NAME; + jdbcTemplate.delete(query); } } diff --git a/src/test/java/db/DBServiceTest.java b/src/test/java/db/DBServiceTest.java index 88ac6d55bfd..8d30691cf13 100644 --- a/src/test/java/db/DBServiceTest.java +++ b/src/test/java/db/DBServiceTest.java @@ -37,7 +37,7 @@ void rollback() { @Test void 이전_게임_데이터가_존재한다() { - assertThat(dbService.doesPreviousDataExist()).isTrue(); + assertThat(dbService.isPreviousDataExist()).isTrue(); } @Test @@ -79,6 +79,6 @@ void rollback() { void 모든_데이터를_삭제한다() { dbService.deletePreviousData(); - assertThat(dbService.doesPreviousDataExist()).isFalse(); + assertThat(dbService.isPreviousDataExist()).isFalse(); } } diff --git a/src/test/java/db/PieceDaoTest.java b/src/test/java/db/PieceDaoTest.java index 33c422ff99f..41c97a37cde 100644 --- a/src/test/java/db/PieceDaoTest.java +++ b/src/test/java/db/PieceDaoTest.java @@ -19,7 +19,7 @@ void rollback() { final var pieceDto = new PieceDto("A", "3", "WHITE", "PAWN"); pieceDao.add(pieceDto); - PieceDto findPieceDto = pieceDao.find("A", "3"); + PieceDto findPieceDto = pieceDao.findOne("A", "3"); assertThat(findPieceDto).isEqualTo(pieceDto); } @@ -29,7 +29,7 @@ void rollback() { final var pieceDto = new PieceDto("A", "3", "WHITE", "PAWN"); pieceDao.add(pieceDto); - PieceDto findPiece = pieceDao.find("A", "3"); + PieceDto findPiece = pieceDao.findOne("A", "3"); assertThat(findPiece.color()).isEqualTo("WHITE"); assertThat(findPiece.type()).isEqualTo("PAWN"); @@ -57,6 +57,6 @@ void rollback() { pieceDao.add(pieceDtoB); pieceDao.add(pieceDtoC); - assertThat(pieceDao.count()).isEqualTo(3); + assertThat(pieceDao.hasRecords()).isTrue(); } } From e5652d153ed95ed7877896436c45082b1a39bbe3 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Wed, 27 Mar 2024 16:41:11 +0900 Subject: [PATCH 38/94] =?UTF-8?q?rename:=20DAO=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=9D=B4=EB=8F=99,?= =?UTF-8?q?=20=EC=9D=B4=EB=A6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/ChessController.java | 24 +++++++++---------- src/main/java/db/JdbcTemplate.java | 2 +- .../DaoService.java} | 15 ++++++++---- .../java/{db => repository}/PieceDao.java | 6 +++-- src/main/java/{db => repository}/TurnDao.java | 6 +++-- .../DaoServiceTest.java} | 24 +++++++++---------- .../java/{db => repository}/PieceDaoTest.java | 2 +- .../java/{db => repository}/TurnDaoTest.java | 2 +- 8 files changed, 46 insertions(+), 35 deletions(-) rename src/main/java/{db/DBService.java => repository/DaoService.java} (69%) rename src/main/java/{db => repository}/PieceDao.java (93%) rename src/main/java/{db => repository}/TurnDao.java (91%) rename src/test/java/{db/DBServiceTest.java => repository/DaoServiceTest.java} (76%) rename src/test/java/{db => repository}/PieceDaoTest.java (98%) rename src/test/java/{db => repository}/TurnDaoTest.java (95%) diff --git a/src/main/java/controller/ChessController.java b/src/main/java/controller/ChessController.java index b90784e88a9..4c5f0a4b5e5 100644 --- a/src/main/java/controller/ChessController.java +++ b/src/main/java/controller/ChessController.java @@ -2,7 +2,7 @@ import controller.command.Command; import controller.command.EndOnCommand; -import db.DBService; +import repository.DaoService; import domain.board.ChessBoard; import domain.board.ChessBoardFactory; import domain.dto.TurnDto; @@ -19,8 +19,8 @@ public ChessController(InputView inputView, OutputView outputView) { } public void start() { - DBService dbService = new DBService(); - ChessBoard board = createChessBoard(dbService); + DaoService daoService = new DaoService(); + ChessBoard board = createChessBoard(daoService); outputView.printGameGuideMessage(); Command command = readStartCommandUntilValid(); @@ -29,13 +29,13 @@ public void start() { command = readNextCommand(board); } command.execute(board, outputView); - updateGameStatus(dbService, board); + updateGameStatus(daoService, board); } - private ChessBoard createChessBoard(DBService dbService) { - if (dbService.isPreviousDataExist()) { - TurnDto turnDto = dbService.loadPreviousTurn(); - return ChessBoardFactory.loadPreviousChessBoard(dbService.loadPreviousData(), turnDto.getTurn()); + private ChessBoard createChessBoard(DaoService daoService) { + if (daoService.isPreviousDataExist()) { + TurnDto turnDto = daoService.loadPreviousTurn(); + return ChessBoardFactory.loadPreviousChessBoard(daoService.loadPreviousData(), turnDto.getTurn()); } return ChessBoardFactory.createInitialChessBoard(); } @@ -65,12 +65,12 @@ private Command readCommandUntilValid() { } } - private void updateGameStatus(final DBService dbService, final ChessBoard board) { + private void updateGameStatus(final DaoService daoService, final ChessBoard board) { if (board.isKingNotExist()) { - dbService.deletePreviousData(); + daoService.deletePreviousData(); return; } - dbService.updatePiece(board.getPieces()); - dbService.updateTurn(board.getTurn()); + daoService.updatePiece(board.getPieces()); + daoService.updateTurn(board.getTurn()); } } diff --git a/src/main/java/db/JdbcTemplate.java b/src/main/java/db/JdbcTemplate.java index 8062983d517..272b4ec06cb 100644 --- a/src/main/java/db/JdbcTemplate.java +++ b/src/main/java/db/JdbcTemplate.java @@ -13,7 +13,7 @@ public JdbcTemplate() { this.connectionManager = new ConnectionManager(); } - void add(final String query, final String... parameters) { + public void add(final String query, final String... parameters) { execute(query, parameters); } diff --git a/src/main/java/db/DBService.java b/src/main/java/repository/DaoService.java similarity index 69% rename from src/main/java/db/DBService.java rename to src/main/java/repository/DaoService.java index 15cc8827a10..46654381756 100644 --- a/src/main/java/db/DBService.java +++ b/src/main/java/repository/DaoService.java @@ -1,13 +1,20 @@ -package db; +package repository; +import db.JdbcTemplate; import domain.dto.PieceDto; import domain.dto.TurnDto; import java.util.List; -public class DBService { - private final PieceDao pieceDao = new PieceDao(); - private final TurnDao turnDao = new TurnDao(); +public class DaoService { + private final PieceDao pieceDao; + private final TurnDao turnDao; + + public DaoService() { + final JdbcTemplate jdbcTemplate = new JdbcTemplate(); + this.pieceDao = new PieceDao(jdbcTemplate); + this.turnDao = new TurnDao(jdbcTemplate); + } public boolean isPreviousDataExist() { return pieceDao.hasRecords(); diff --git a/src/main/java/db/PieceDao.java b/src/main/java/repository/PieceDao.java similarity index 93% rename from src/main/java/db/PieceDao.java rename to src/main/java/repository/PieceDao.java index a38b0708816..12b8699903f 100644 --- a/src/main/java/db/PieceDao.java +++ b/src/main/java/repository/PieceDao.java @@ -1,5 +1,7 @@ -package db; +package repository; +import db.JdbcTemplate; +import db.RowMapper; import domain.dto.PieceDto; import java.util.List; @@ -19,7 +21,7 @@ public class PieceDao { this(new JdbcTemplate()); } - private PieceDao(final JdbcTemplate jdbcTemplate) { + PieceDao(final JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } diff --git a/src/main/java/db/TurnDao.java b/src/main/java/repository/TurnDao.java similarity index 91% rename from src/main/java/db/TurnDao.java rename to src/main/java/repository/TurnDao.java index ec0aeaa38be..6cc7e71888d 100644 --- a/src/main/java/db/TurnDao.java +++ b/src/main/java/repository/TurnDao.java @@ -1,5 +1,7 @@ -package db; +package repository; +import db.JdbcTemplate; +import db.RowMapper; import domain.dto.TurnDto; import java.util.List; @@ -15,7 +17,7 @@ public class TurnDao { this(new JdbcTemplate()); } - private TurnDao(final JdbcTemplate jdbcTemplate) { + TurnDao(final JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } diff --git a/src/test/java/db/DBServiceTest.java b/src/test/java/repository/DaoServiceTest.java similarity index 76% rename from src/test/java/db/DBServiceTest.java rename to src/test/java/repository/DaoServiceTest.java index 8d30691cf13..4bb37d3635c 100644 --- a/src/test/java/db/DBServiceTest.java +++ b/src/test/java/repository/DaoServiceTest.java @@ -1,4 +1,4 @@ -package db; +package repository; import domain.dto.PieceDto; import domain.dto.TurnDto; @@ -11,7 +11,7 @@ import static org.assertj.core.api.Assertions.assertThat; -class DBServiceTest { +class DaoServiceTest { private static final PieceDto A2WhitePawn = new PieceDto("A", "2", "WHITE", "PAWN"); private static final PieceDto B2WhitePawn = new PieceDto("B", "2", "WHITE", "PAWN"); private static final PieceDto C2WhitePawn = new PieceDto("C", "2", "WHITE", "PAWN"); @@ -19,7 +19,7 @@ class DBServiceTest { private final PieceDao pieceDao = new PieceDao(); private final TurnDao turnDao = new TurnDao(); - private final DBService dbService = new DBService(); + private final DaoService daoService = new DaoService(); @BeforeEach void setData() { @@ -37,18 +37,18 @@ void rollback() { @Test void 이전_게임_데이터가_존재한다() { - assertThat(dbService.isPreviousDataExist()).isTrue(); + assertThat(daoService.isPreviousDataExist()).isTrue(); } @Test void 이전_게임_데이터를_불러온다() { - assertThat(dbService.loadPreviousData()) + assertThat(daoService.loadPreviousData()) .containsExactlyInAnyOrder(A2WhitePawn, B2WhitePawn, C2WhitePawn); } @Test void 이전_게임의_턴_데이터를_불러온다() { - assertThat(dbService.loadPreviousTurn().getTurn()) + assertThat(daoService.loadPreviousTurn().getTurn()) .isEqualTo(Color.WHITE); } @@ -60,9 +60,9 @@ void rollback() { List pieceDtos = List.of(A3WhitePawn, B3WhitePawn, C3WhitePawn); - dbService.updatePiece(pieceDtos); + daoService.updatePiece(pieceDtos); - assertThat(dbService.loadPreviousData()) + assertThat(daoService.loadPreviousData()) .containsExactlyInAnyOrder(A3WhitePawn, B3WhitePawn, C3WhitePawn); } @@ -70,15 +70,15 @@ void rollback() { void 턴_데이터를_갱신한다() { TurnDto blackTurn = new TurnDto("BLACK"); - dbService.updateTurn(blackTurn); + daoService.updateTurn(blackTurn); - assertThat(dbService.loadPreviousTurn().getTurn()).isEqualTo(Color.BLACK); + assertThat(daoService.loadPreviousTurn().getTurn()).isEqualTo(Color.BLACK); } @Test void 모든_데이터를_삭제한다() { - dbService.deletePreviousData(); + daoService.deletePreviousData(); - assertThat(dbService.isPreviousDataExist()).isFalse(); + assertThat(daoService.isPreviousDataExist()).isFalse(); } } diff --git a/src/test/java/db/PieceDaoTest.java b/src/test/java/repository/PieceDaoTest.java similarity index 98% rename from src/test/java/db/PieceDaoTest.java rename to src/test/java/repository/PieceDaoTest.java index 41c97a37cde..ef971b18f09 100644 --- a/src/test/java/db/PieceDaoTest.java +++ b/src/test/java/repository/PieceDaoTest.java @@ -1,4 +1,4 @@ -package db; +package repository; import domain.dto.PieceDto; import org.junit.jupiter.api.AfterEach; diff --git a/src/test/java/db/TurnDaoTest.java b/src/test/java/repository/TurnDaoTest.java similarity index 95% rename from src/test/java/db/TurnDaoTest.java rename to src/test/java/repository/TurnDaoTest.java index bf5c3c241dc..b57e7000354 100644 --- a/src/test/java/db/TurnDaoTest.java +++ b/src/test/java/repository/TurnDaoTest.java @@ -1,4 +1,4 @@ -package db; +package repository; import domain.dto.TurnDto; import domain.piece.Color; From 6aa638d23d53e8037289f7a1f0129adc1b9f4075 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Wed, 27 Mar 2024 19:31:45 +0900 Subject: [PATCH 39/94] =?UTF-8?q?rename:=20DTO=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/ChessController.java | 2 +- src/main/java/domain/board/ChessBoard.java | 4 ++-- src/main/java/domain/board/ChessBoardFactory.java | 2 +- src/main/java/{domain => }/dto/PieceDto.java | 2 +- src/main/java/{domain => }/dto/TurnDto.java | 2 +- src/main/java/repository/DaoService.java | 4 ++-- src/main/java/repository/PieceDao.java | 2 +- src/main/java/repository/TurnDao.java | 2 +- src/test/java/domain/dto/PieceDtoTest.java | 1 + src/test/java/repository/DaoServiceTest.java | 4 ++-- src/test/java/repository/PieceDaoTest.java | 2 +- src/test/java/repository/TurnDaoTest.java | 2 +- 12 files changed, 15 insertions(+), 14 deletions(-) rename src/main/java/{domain => }/dto/PieceDto.java (97%) rename src/main/java/{domain => }/dto/TurnDto.java (87%) diff --git a/src/main/java/controller/ChessController.java b/src/main/java/controller/ChessController.java index 4c5f0a4b5e5..4741b6c6c70 100644 --- a/src/main/java/controller/ChessController.java +++ b/src/main/java/controller/ChessController.java @@ -5,7 +5,7 @@ import repository.DaoService; import domain.board.ChessBoard; import domain.board.ChessBoardFactory; -import domain.dto.TurnDto; +import dto.TurnDto; import view.InputView; import view.OutputView; diff --git a/src/main/java/domain/board/ChessBoard.java b/src/main/java/domain/board/ChessBoard.java index 246e75b504d..624cc4bee44 100644 --- a/src/main/java/domain/board/ChessBoard.java +++ b/src/main/java/domain/board/ChessBoard.java @@ -1,7 +1,7 @@ package domain.board; -import domain.dto.PieceDto; -import domain.dto.TurnDto; +import dto.PieceDto; +import dto.TurnDto; import domain.piece.Color; import domain.piece.Empty; import domain.piece.Piece; diff --git a/src/main/java/domain/board/ChessBoardFactory.java b/src/main/java/domain/board/ChessBoardFactory.java index 352ec4f21f2..fe316208f36 100644 --- a/src/main/java/domain/board/ChessBoardFactory.java +++ b/src/main/java/domain/board/ChessBoardFactory.java @@ -1,6 +1,6 @@ package domain.board; -import domain.dto.PieceDto; +import dto.PieceDto; import domain.piece.Color; import domain.piece.Piece; import domain.piece.nonpawn.Bishop; diff --git a/src/main/java/domain/dto/PieceDto.java b/src/main/java/dto/PieceDto.java similarity index 97% rename from src/main/java/domain/dto/PieceDto.java rename to src/main/java/dto/PieceDto.java index 52a3af1ed42..70e87feea7e 100644 --- a/src/main/java/domain/dto/PieceDto.java +++ b/src/main/java/dto/PieceDto.java @@ -1,4 +1,4 @@ -package domain.dto; +package dto; import domain.piece.Color; import domain.piece.Piece; diff --git a/src/main/java/domain/dto/TurnDto.java b/src/main/java/dto/TurnDto.java similarity index 87% rename from src/main/java/domain/dto/TurnDto.java rename to src/main/java/dto/TurnDto.java index 874c4d86ff0..e350c4bca7f 100644 --- a/src/main/java/domain/dto/TurnDto.java +++ b/src/main/java/dto/TurnDto.java @@ -1,4 +1,4 @@ -package domain.dto; +package dto; import domain.piece.Color; diff --git a/src/main/java/repository/DaoService.java b/src/main/java/repository/DaoService.java index 46654381756..c3b3143b741 100644 --- a/src/main/java/repository/DaoService.java +++ b/src/main/java/repository/DaoService.java @@ -1,8 +1,8 @@ package repository; import db.JdbcTemplate; -import domain.dto.PieceDto; -import domain.dto.TurnDto; +import dto.PieceDto; +import dto.TurnDto; import java.util.List; diff --git a/src/main/java/repository/PieceDao.java b/src/main/java/repository/PieceDao.java index 12b8699903f..1a47e84ccea 100644 --- a/src/main/java/repository/PieceDao.java +++ b/src/main/java/repository/PieceDao.java @@ -2,7 +2,7 @@ import db.JdbcTemplate; import db.RowMapper; -import domain.dto.PieceDto; +import dto.PieceDto; import java.util.List; diff --git a/src/main/java/repository/TurnDao.java b/src/main/java/repository/TurnDao.java index 6cc7e71888d..c183f6284ca 100644 --- a/src/main/java/repository/TurnDao.java +++ b/src/main/java/repository/TurnDao.java @@ -2,7 +2,7 @@ import db.JdbcTemplate; import db.RowMapper; -import domain.dto.TurnDto; +import dto.TurnDto; import java.util.List; diff --git a/src/test/java/domain/dto/PieceDtoTest.java b/src/test/java/domain/dto/PieceDtoTest.java index d569dd03294..363978233d2 100644 --- a/src/test/java/domain/dto/PieceDtoTest.java +++ b/src/test/java/domain/dto/PieceDtoTest.java @@ -12,6 +12,7 @@ import domain.position.File; import domain.position.Position; import domain.position.Rank; +import dto.PieceDto; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; diff --git a/src/test/java/repository/DaoServiceTest.java b/src/test/java/repository/DaoServiceTest.java index 4bb37d3635c..1ef351898e0 100644 --- a/src/test/java/repository/DaoServiceTest.java +++ b/src/test/java/repository/DaoServiceTest.java @@ -1,7 +1,7 @@ package repository; -import domain.dto.PieceDto; -import domain.dto.TurnDto; +import dto.PieceDto; +import dto.TurnDto; import domain.piece.Color; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; diff --git a/src/test/java/repository/PieceDaoTest.java b/src/test/java/repository/PieceDaoTest.java index ef971b18f09..ba2b9721663 100644 --- a/src/test/java/repository/PieceDaoTest.java +++ b/src/test/java/repository/PieceDaoTest.java @@ -1,6 +1,6 @@ package repository; -import domain.dto.PieceDto; +import dto.PieceDto; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; diff --git a/src/test/java/repository/TurnDaoTest.java b/src/test/java/repository/TurnDaoTest.java index b57e7000354..82b3d3f1c58 100644 --- a/src/test/java/repository/TurnDaoTest.java +++ b/src/test/java/repository/TurnDaoTest.java @@ -1,6 +1,6 @@ package repository; -import domain.dto.TurnDto; +import dto.TurnDto; import domain.piece.Color; import org.junit.jupiter.api.Test; From 75338a7b61d85230e8a85b2385ba6cded90e39a5 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Thu, 28 Mar 2024 00:31:14 +0900 Subject: [PATCH 40/94] =?UTF-8?q?refactor:=20=EC=BB=A4=EB=A7=A8=EB=93=9C?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=EA=B3=BC=20=EA=B2=80=EC=A6=9D=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EC=B1=85=EC=9E=84=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/ChessController.java | 21 +++++---- .../java/controller/command/EndOnCommand.java | 14 ++++++ .../controller/command/MoveOnCommand.java | 13 ++++-- .../controller/command/StartOnCommand.java | 14 ++++++ .../controller/command/StatusOnCommand.java | 14 +++++- src/main/java/view/CommandType.java | 46 ------------------- src/main/java/view/InputView.java | 39 ++++------------ src/main/java/view/MessageResolver.java | 6 +-- src/main/java/view/command/CommandInput.java | 44 ++++++++++++++++++ src/main/java/view/command/CommandType.java | 39 ++++++++++++++++ 10 files changed, 156 insertions(+), 94 deletions(-) delete mode 100644 src/main/java/view/CommandType.java create mode 100644 src/main/java/view/command/CommandInput.java create mode 100644 src/main/java/view/command/CommandType.java diff --git a/src/main/java/controller/ChessController.java b/src/main/java/controller/ChessController.java index 4741b6c6c70..c58cdeba942 100644 --- a/src/main/java/controller/ChessController.java +++ b/src/main/java/controller/ChessController.java @@ -2,10 +2,11 @@ import controller.command.Command; import controller.command.EndOnCommand; -import repository.DaoService; +import controller.command.StartOnCommand; import domain.board.ChessBoard; import domain.board.ChessBoardFactory; import dto.TurnDto; +import repository.DaoService; import view.InputView; import view.OutputView; @@ -23,7 +24,7 @@ public void start() { ChessBoard board = createChessBoard(daoService); outputView.printGameGuideMessage(); - Command command = readStartCommandUntilValid(); + Command command = new StartOnCommand(); while (command.isNotEnded()) { command.execute(board, outputView); command = readNextCommand(board); @@ -40,14 +41,14 @@ private ChessBoard createChessBoard(DaoService daoService) { return ChessBoardFactory.createInitialChessBoard(); } - private Command readStartCommandUntilValid() { - try { - return inputView.readStartCommand(); - } catch (Exception e) { - outputView.printErrorMessage(e.getMessage()); - return readStartCommandUntilValid(); - } - } +// private Command readStartCommandUntilValid() { +// try { +// return inputView.readStartCommand(); +// } catch (Exception e) { +// outputView.printErrorMessage(e.getMessage()); +// return readStartCommandUntilValid(); +// } +// } private Command readNextCommand(final ChessBoard board) { if (board.isKingNotExist()) { diff --git a/src/main/java/controller/command/EndOnCommand.java b/src/main/java/controller/command/EndOnCommand.java index d4c83efd282..b9ee0d6133d 100644 --- a/src/main/java/controller/command/EndOnCommand.java +++ b/src/main/java/controller/command/EndOnCommand.java @@ -3,7 +3,21 @@ import domain.board.ChessBoard; import view.OutputView; +import java.util.List; + public class EndOnCommand implements Command { + private static final int ARGUMENT_SIZE = 0; + + public EndOnCommand() { + this(List.of()); + } + + public EndOnCommand(final List arguments) { + if (arguments.size() != ARGUMENT_SIZE) { + throw new IllegalArgumentException(); + } + } + @Override public void execute(final ChessBoard board, final OutputView outputView) { outputView.printScore(board.calculateScore()); diff --git a/src/main/java/controller/command/MoveOnCommand.java b/src/main/java/controller/command/MoveOnCommand.java index afe5612b68f..2c270ea5d6c 100644 --- a/src/main/java/controller/command/MoveOnCommand.java +++ b/src/main/java/controller/command/MoveOnCommand.java @@ -4,13 +4,20 @@ import domain.position.Position; import view.OutputView; +import java.util.List; + public class MoveOnCommand implements Command { + private static final int ARGUMENT_SIZE = 2; + private final Position source; private final Position target; - public MoveOnCommand(final Position source, final Position target) { - this.source = source; - this.target = target; + public MoveOnCommand(final List arguments) { + if (arguments.size() != ARGUMENT_SIZE) { + throw new IllegalArgumentException(); + } + this.source = new Position(arguments.get(0)); + this.target = new Position(arguments.get(1)); } @Override diff --git a/src/main/java/controller/command/StartOnCommand.java b/src/main/java/controller/command/StartOnCommand.java index b900ef6e972..187d37e080a 100644 --- a/src/main/java/controller/command/StartOnCommand.java +++ b/src/main/java/controller/command/StartOnCommand.java @@ -3,7 +3,21 @@ import domain.board.ChessBoard; import view.OutputView; +import java.util.List; + public class StartOnCommand implements Command { + private static final int ARGUMENT_SIZE = 0; + + public StartOnCommand() { + this(List.of()); + } + + public StartOnCommand(final List arguments) { + if (arguments.size() != ARGUMENT_SIZE) { + throw new IllegalArgumentException(); + } + } + @Override public void execute(final ChessBoard board, final OutputView outputView) { outputView.printBoard(board); diff --git a/src/main/java/controller/command/StatusOnCommand.java b/src/main/java/controller/command/StatusOnCommand.java index 47974c63dee..e5bcd5572be 100644 --- a/src/main/java/controller/command/StatusOnCommand.java +++ b/src/main/java/controller/command/StatusOnCommand.java @@ -4,10 +4,20 @@ import domain.board.Score; import view.OutputView; -public class StatusOnCommand implements Command{ +import java.util.List; + +public class StatusOnCommand implements Command { + private static final int ARGUMENT_SIZE = 0; + + public StatusOnCommand(final List arguments) { + if (arguments.size() != ARGUMENT_SIZE) { + throw new IllegalArgumentException(); + } + } + @Override public void execute(final ChessBoard board, final OutputView outputView) { - Score score = board.calculateScore(); + final Score score = board.calculateScore(); outputView.printScore(score); } diff --git a/src/main/java/view/CommandType.java b/src/main/java/view/CommandType.java deleted file mode 100644 index a807ec45171..00000000000 --- a/src/main/java/view/CommandType.java +++ /dev/null @@ -1,46 +0,0 @@ -package view; - -import controller.command.Command; -import controller.command.EndOnCommand; -import controller.command.MoveOnCommand; -import controller.command.StartOnCommand; -import controller.command.StatusOnCommand; -import domain.position.Position; - -import java.util.Arrays; -import java.util.function.Function; - -public enum CommandType { - START(tokens -> isCommand(tokens, "START", 1), - (tokens) -> new StartOnCommand()), - END(tokens -> isCommand(tokens, "END", 1), - (tokens) -> new EndOnCommand()), - STATUS(tokens -> isCommand(tokens, "STATUS", 1), - (tokens) -> new StatusOnCommand()), - MOVE(tokens -> isCommand(tokens, "MOVE", 3), - (tokens) -> new MoveOnCommand(new Position(tokens[1]), new Position(tokens[2]))); - - private final Function validator; - private final Function command; - - CommandType(final Function validator, final Function command) { - this.validator = validator; - this.command = command; - } - - public static Command getCommand(String[] tokens) { - CommandType findCommand = Arrays.stream(CommandType.values()) - .filter(command -> command.validator.apply(tokens)) - .findFirst() - .orElseThrow(IllegalArgumentException::new); - return findCommand.command.apply(tokens); - } - - private static boolean isCommand(String[] tokens, String commandName, int size) { - return tokens.length == size && commandName.equals(tokens[0]); - } - - public String message() { - return name().toLowerCase(); - } -} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 19f9e183246..d7ad96240b0 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,7 +1,8 @@ package view; import controller.command.Command; -import controller.command.StartOnCommand; +import view.command.CommandInput; +import view.command.CommandType; import java.util.Scanner; @@ -15,42 +16,20 @@ public InputView() { this.scanner = new Scanner(System.in); } - public Command readStartCommand() { - String[] tokens = readUserInput(); - if (tokens.length == 1 && CommandType.START.name().equals(tokens[0])) { - return new StartOnCommand(); - } - throw new IllegalArgumentException(GAME_NOT_STARTED_ERROR_MESSAGE); - } +// public Command readStartCommand() { +// return CommandType.getCommand(readCommandInput()); +// } public Command readCommand() { - String[] tokens = readUserInput(); try { - validateCommand(tokens); - return CommandType.getCommand(tokens); + CommandInput input = readCommandInput(); + return CommandType.getCommand(input); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(WRONG_COMMAND_ERROR_MESSAGE); } } - private void validateCommand(String[] tokens) { - for (int i = 1; i < tokens.length; i++) { - validatePositionFormat(tokens[i]); - } - } - - private void validatePositionFormat(String token) { - if (token.length() != 2) { - throw new IllegalArgumentException(); - } - try { - Integer.parseInt(token.substring(1)); - } catch (NumberFormatException e) { - throw new IllegalArgumentException(); - } - } - - private String[] readUserInput() { - return scanner.nextLine().trim().toUpperCase().split(" "); + private CommandInput readCommandInput() { + return new CommandInput(scanner.nextLine()); } } diff --git a/src/main/java/view/MessageResolver.java b/src/main/java/view/MessageResolver.java index a1f0bd024b0..187e1dc4ff5 100644 --- a/src/main/java/view/MessageResolver.java +++ b/src/main/java/view/MessageResolver.java @@ -14,9 +14,9 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; -import static view.CommandType.END; -import static view.CommandType.MOVE; -import static view.CommandType.START; +import static view.command.CommandType.END; +import static view.command.CommandType.MOVE; +import static view.command.CommandType.START; public class MessageResolver { public static final int BOARD_LENGTH = 8; diff --git a/src/main/java/view/command/CommandInput.java b/src/main/java/view/command/CommandInput.java new file mode 100644 index 00000000000..f13db2253dd --- /dev/null +++ b/src/main/java/view/command/CommandInput.java @@ -0,0 +1,44 @@ +package view.command; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.regex.Pattern; + +public class CommandInput { + private static final Pattern POSITION_INPUT_PATTERN = Pattern.compile("^[a-h][1-8]$"); + + private final List inputs; + + public CommandInput(final String input) { + this(List.of(input.split(" "))); + } + + private CommandInput(final List inputs) { + validatePositions(inputs.subList(1, inputs.size())); + this.inputs = inputs; + } + + private void validatePositions(final List inputs) { + inputs.forEach(this::validatePositionFormat); + } + + private void validatePositionFormat(final String positionInput) { + if (!POSITION_INPUT_PATTERN.matcher(positionInput).matches()) { + throw new IllegalArgumentException(); + } + } + + public String prefix() { + if (inputs.isEmpty()) { + throw new NoSuchElementException(); + } + return inputs.get(0); + } + + public List getArguments() { + return inputs.stream() + .map(String::toUpperCase) + .toList() + .subList(1, inputs.size()); + } +} diff --git a/src/main/java/view/command/CommandType.java b/src/main/java/view/command/CommandType.java new file mode 100644 index 00000000000..15424f7f5f8 --- /dev/null +++ b/src/main/java/view/command/CommandType.java @@ -0,0 +1,39 @@ +package view.command; + +import controller.command.Command; +import controller.command.EndOnCommand; +import controller.command.MoveOnCommand; +import controller.command.StartOnCommand; +import controller.command.StatusOnCommand; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; + +public enum CommandType { + START("start", StartOnCommand::new), + END("end", EndOnCommand::new), + STATUS("status", StatusOnCommand::new), + MOVE("move", MoveOnCommand::new); + + private final String command; + private final Function, Command> mapper; + + CommandType(final String command, final Function, Command> mapper) { + this.command = command; + this.mapper = mapper; + } + + public static Command getCommand(final CommandInput input) { + final CommandType commandType = Arrays.stream(CommandType.values()) + .filter(command -> input.prefix().equals(command.command)) + .findFirst() + .orElseThrow(IllegalArgumentException::new); + + return commandType.mapper.apply(input.getArguments()); + } + + public String message() { + return this.command; + } +} From 4b876b45f5abc1f63f5aad68006ab783d561500e Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Fri, 29 Mar 2024 00:46:16 +0900 Subject: [PATCH 41/94] =?UTF-8?q?refactor:=20turn=EC=9D=84=20GameStatus?= =?UTF-8?q?=EB=A1=9C=20=EB=8C=80=EC=B2=B4,=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EB=A1=9C=EC=A7=81=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/ChessController.java | 30 +++--------- src/main/java/controller/command/Command.java | 2 - .../java/controller/command/EndOnCommand.java | 10 ++-- .../controller/command/MoveOnCommand.java | 20 ++++++-- .../controller/command/StartOnCommand.java | 14 ++++-- .../controller/command/StatusOnCommand.java | 16 +++++-- src/main/java/domain/board/ChessBoard.java | 46 ++++++++++++------- src/main/java/domain/board/GameStatus.java | 23 ++++++++++ 8 files changed, 102 insertions(+), 59 deletions(-) create mode 100644 src/main/java/domain/board/GameStatus.java diff --git a/src/main/java/controller/ChessController.java b/src/main/java/controller/ChessController.java index c58cdeba942..253f9b29956 100644 --- a/src/main/java/controller/ChessController.java +++ b/src/main/java/controller/ChessController.java @@ -1,8 +1,6 @@ package controller; import controller.command.Command; -import controller.command.EndOnCommand; -import controller.command.StartOnCommand; import domain.board.ChessBoard; import domain.board.ChessBoardFactory; import dto.TurnDto; @@ -24,12 +22,12 @@ public void start() { ChessBoard board = createChessBoard(daoService); outputView.printGameGuideMessage(); - Command command = new StartOnCommand(); - while (command.isNotEnded()) { + Command command; + do { + command = readCommandUntilValid(); command.execute(board, outputView); - command = readNextCommand(board); - } - command.execute(board, outputView); + } while (board.isGameRunning()); + updateGameStatus(daoService, board); } @@ -41,22 +39,6 @@ private ChessBoard createChessBoard(DaoService daoService) { return ChessBoardFactory.createInitialChessBoard(); } -// private Command readStartCommandUntilValid() { -// try { -// return inputView.readStartCommand(); -// } catch (Exception e) { -// outputView.printErrorMessage(e.getMessage()); -// return readStartCommandUntilValid(); -// } -// } - - private Command readNextCommand(final ChessBoard board) { - if (board.isKingNotExist()) { - return new EndOnCommand(); - } - return readCommandUntilValid(); - } - private Command readCommandUntilValid() { try { return inputView.readCommand(); @@ -72,6 +54,6 @@ private void updateGameStatus(final DaoService daoService, final ChessBoard boar return; } daoService.updatePiece(board.getPieces()); - daoService.updateTurn(board.getTurn()); + daoService.updateTurn(board.getStatus()); } } diff --git a/src/main/java/controller/command/Command.java b/src/main/java/controller/command/Command.java index 4afdb91a1f0..6d1fb11eb10 100644 --- a/src/main/java/controller/command/Command.java +++ b/src/main/java/controller/command/Command.java @@ -5,6 +5,4 @@ public interface Command { void execute(ChessBoard board, OutputView outputView); - - boolean isNotEnded(); } diff --git a/src/main/java/controller/command/EndOnCommand.java b/src/main/java/controller/command/EndOnCommand.java index b9ee0d6133d..b032fea97cc 100644 --- a/src/main/java/controller/command/EndOnCommand.java +++ b/src/main/java/controller/command/EndOnCommand.java @@ -13,6 +13,10 @@ public EndOnCommand() { } public EndOnCommand(final List arguments) { + validateArgumentSize(arguments); + } + + private void validateArgumentSize(final List arguments) { if (arguments.size() != ARGUMENT_SIZE) { throw new IllegalArgumentException(); } @@ -20,11 +24,7 @@ public EndOnCommand(final List arguments) { @Override public void execute(final ChessBoard board, final OutputView outputView) { + board.end(); outputView.printScore(board.calculateScore()); } - - @Override - public boolean isNotEnded() { - return false; - } } diff --git a/src/main/java/controller/command/MoveOnCommand.java b/src/main/java/controller/command/MoveOnCommand.java index 2c270ea5d6c..20d15010a1a 100644 --- a/src/main/java/controller/command/MoveOnCommand.java +++ b/src/main/java/controller/command/MoveOnCommand.java @@ -1,6 +1,7 @@ package controller.command; import domain.board.ChessBoard; +import domain.board.GameStatus; import domain.position.Position; import view.OutputView; @@ -13,15 +14,20 @@ public class MoveOnCommand implements Command { private final Position target; public MoveOnCommand(final List arguments) { + validateArgumentSize(arguments); + this.source = new Position(arguments.get(0)); + this.target = new Position(arguments.get(1)); + } + + private void validateArgumentSize(final List arguments) { if (arguments.size() != ARGUMENT_SIZE) { throw new IllegalArgumentException(); } - this.source = new Position(arguments.get(0)); - this.target = new Position(arguments.get(1)); } @Override public void execute(final ChessBoard board, final OutputView outputView) { + validateGameStatus(board); try { board.move(source, target); outputView.printBoard(board); @@ -30,8 +36,12 @@ public void execute(final ChessBoard board, final OutputView outputView) { } } - @Override - public boolean isNotEnded() { - return true; + private void validateGameStatus(final ChessBoard board) { + if (board.getStatus() == GameStatus.NOT_STARTED) { + throw new IllegalStateException("게임을 먼저 시작해 주세요."); + } + if (board.getStatus() == GameStatus.ENDED || board.getStatus() == GameStatus.KING_IS_DEAD) { + throw new IllegalStateException("게임이 종료됐습니다."); + } } } diff --git a/src/main/java/controller/command/StartOnCommand.java b/src/main/java/controller/command/StartOnCommand.java index 187d37e080a..7f8a0362a41 100644 --- a/src/main/java/controller/command/StartOnCommand.java +++ b/src/main/java/controller/command/StartOnCommand.java @@ -1,6 +1,7 @@ package controller.command; import domain.board.ChessBoard; +import domain.board.GameStatus; import view.OutputView; import java.util.List; @@ -13,6 +14,10 @@ public StartOnCommand() { } public StartOnCommand(final List arguments) { + validateArgumentSize(arguments); + } + + private void validateArgumentSize(final List arguments) { if (arguments.size() != ARGUMENT_SIZE) { throw new IllegalArgumentException(); } @@ -20,11 +25,14 @@ public StartOnCommand(final List arguments) { @Override public void execute(final ChessBoard board, final OutputView outputView) { + validateGameStatus(board); + board.start(); outputView.printBoard(board); } - @Override - public boolean isNotEnded() { - return true; + private void validateGameStatus(final ChessBoard board) { + if (board.getStatus() != GameStatus.NOT_STARTED) { + throw new IllegalStateException("게임이 이미 시작됐습니다."); + } } } diff --git a/src/main/java/controller/command/StatusOnCommand.java b/src/main/java/controller/command/StatusOnCommand.java index e5bcd5572be..213b2e5b7cb 100644 --- a/src/main/java/controller/command/StatusOnCommand.java +++ b/src/main/java/controller/command/StatusOnCommand.java @@ -1,6 +1,7 @@ package controller.command; import domain.board.ChessBoard; +import domain.board.GameStatus; import domain.board.Score; import view.OutputView; @@ -10,6 +11,10 @@ public class StatusOnCommand implements Command { private static final int ARGUMENT_SIZE = 0; public StatusOnCommand(final List arguments) { + validateArgumentSize(arguments); + } + + private void validateArgumentSize(final List arguments) { if (arguments.size() != ARGUMENT_SIZE) { throw new IllegalArgumentException(); } @@ -17,12 +22,17 @@ public StatusOnCommand(final List arguments) { @Override public void execute(final ChessBoard board, final OutputView outputView) { + validateGameStatus(board); final Score score = board.calculateScore(); outputView.printScore(score); } - @Override - public boolean isNotEnded() { - return true; + private void validateGameStatus(final ChessBoard board) { + if (board.getStatus() == GameStatus.NOT_STARTED) { + throw new IllegalStateException("게임을 먼저 시작해 주세요."); + } + if (board.getStatus() == GameStatus.ENDED || board.getStatus() == GameStatus.KING_IS_DEAD) { + throw new IllegalStateException("게임이 종료됐습니다."); + } } } diff --git a/src/main/java/domain/board/ChessBoard.java b/src/main/java/domain/board/ChessBoard.java index 624cc4bee44..3260f895850 100644 --- a/src/main/java/domain/board/ChessBoard.java +++ b/src/main/java/domain/board/ChessBoard.java @@ -1,13 +1,12 @@ package domain.board; -import dto.PieceDto; -import dto.TurnDto; import domain.piece.Color; import domain.piece.Empty; import domain.piece.Piece; import domain.piece.Type; import domain.position.Position; import domain.position.Route; +import dto.PieceDto; import java.util.Collections; import java.util.HashMap; @@ -16,15 +15,15 @@ public class ChessBoard { private final Map board; - private Color turn; + private GameStatus status; - public ChessBoard(Map board, Color color) { + public ChessBoard(Map board, GameStatus status) { this.board = board; - this.turn = color; + this.status = status; } public ChessBoard(Map board) { - this(new HashMap<>(board), Color.WHITE); + this(new HashMap<>(board), GameStatus.NOT_STARTED); } public void move(final Position source, final Position target) { @@ -45,8 +44,8 @@ private void validateEmptyPiece(final Position source) { private void validateTurn(final Position source) { final Piece piece = findPieceByPosition(source); - if (this.turn.isOpposite(piece.color())) { - throw new IllegalArgumentException("상대 턴입니다."); + if (!this.status.isTurnOf(piece.color())) { + throw new IllegalArgumentException(piece.color() + "의 턴입니다."); } } @@ -68,16 +67,16 @@ private void movePiece(final Position source, final Position target) { board.put(target, piece); } + private Piece findPieceByPosition(final Position position) { + return board.getOrDefault(position, Empty.getInstance()); + } + private void changeTurn() { - if (this.turn.isBlack()) { - this.turn = Color.WHITE; + if (this.status.isTurnOf(Color.BLACK)) { + this.status = GameStatus.WHITE_TURN; return; } - this.turn = Color.BLACK; - } - - private Piece findPieceByPosition(final Position position) { - return board.getOrDefault(position, Empty.getInstance()); + this.status = GameStatus.BLACK_TURN; } public boolean isKingNotExist() { @@ -86,6 +85,18 @@ public boolean isKingNotExist() { .count() != 2; } + public void start() { + this.status = GameStatus.WHITE_TURN; + } + + public void end() { + this.status = GameStatus.ENDED; + } + + public boolean isGameRunning() { + return this.status == GameStatus.ENDED; + } + public Score calculateScore() { return Score.calculate(board); } @@ -100,7 +111,8 @@ public List getPieces() { .toList(); } - public TurnDto getTurn() { - return new TurnDto(this.turn.name()); + // TODO: DTO 수정하기 + public GameStatus getStatus() { + return this.status; } } diff --git a/src/main/java/domain/board/GameStatus.java b/src/main/java/domain/board/GameStatus.java new file mode 100644 index 00000000000..841ad354b7f --- /dev/null +++ b/src/main/java/domain/board/GameStatus.java @@ -0,0 +1,23 @@ +package domain.board; + +import domain.piece.Color; + +import java.util.function.Function; + +public enum GameStatus { + NOT_STARTED(color -> false), + WHITE_TURN(color -> Color.WHITE == color), + BLACK_TURN(color -> Color.BLACK == color), + KING_IS_DEAD(color -> false), + ENDED(color -> false); + + private final Function isSameTurn; + + GameStatus(final Function isSameTurn) { + this.isSameTurn = isSameTurn; + } + + boolean isTurnOf(final Color color) { + return isSameTurn.apply(color); + } +} From a8150aa913b5da5ae7b182e717f6161901950fd4 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Fri, 29 Mar 2024 13:43:29 +0900 Subject: [PATCH 42/94] =?UTF-8?q?refactor:=20GameStatus=EB=A5=BC=20State?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/ChessController.java | 8 ++--- .../java/controller/command/EndOnCommand.java | 4 --- .../controller/command/MoveOnCommand.java | 6 ++-- .../controller/command/StartOnCommand.java | 8 ++--- .../controller/command/StatusOnCommand.java | 6 ++-- src/main/java/domain/board/ChessBoard.java | 33 +++++++++---------- .../java/domain/board/ChessBoardFactory.java | 4 +-- .../board/{GameStatus.java => State.java} | 4 +-- src/main/java/dto/StateDto.java | 15 +++++++++ src/main/java/dto/TurnDto.java | 9 ----- src/main/java/repository/DaoService.java | 18 +++++----- .../{TurnDao.java => StateDao.java} | 26 +++++++-------- .../resources/sql/{pieces.sql => schema.sql} | 6 ++++ src/main/resources/sql/turns.sql | 5 --- .../java/domain/board/ChessBoardTest.java | 20 ++++++----- src/test/java/repository/DaoServiceTest.java | 21 ++++++------ src/test/java/repository/StateDaoTest.java | 19 +++++++++++ src/test/java/repository/TurnDaoTest.java | 19 ----------- 18 files changed, 116 insertions(+), 115 deletions(-) rename src/main/java/domain/board/{GameStatus.java => State.java} (84%) create mode 100644 src/main/java/dto/StateDto.java delete mode 100644 src/main/java/dto/TurnDto.java rename src/main/java/repository/{TurnDao.java => StateDao.java} (58%) rename src/main/resources/sql/{pieces.sql => schema.sql} (71%) delete mode 100644 src/main/resources/sql/turns.sql create mode 100644 src/test/java/repository/StateDaoTest.java delete mode 100644 src/test/java/repository/TurnDaoTest.java diff --git a/src/main/java/controller/ChessController.java b/src/main/java/controller/ChessController.java index 253f9b29956..1c98717e012 100644 --- a/src/main/java/controller/ChessController.java +++ b/src/main/java/controller/ChessController.java @@ -3,7 +3,7 @@ import controller.command.Command; import domain.board.ChessBoard; import domain.board.ChessBoardFactory; -import dto.TurnDto; +import dto.StateDto; import repository.DaoService; import view.InputView; import view.OutputView; @@ -33,8 +33,8 @@ public void start() { private ChessBoard createChessBoard(DaoService daoService) { if (daoService.isPreviousDataExist()) { - TurnDto turnDto = daoService.loadPreviousTurn(); - return ChessBoardFactory.loadPreviousChessBoard(daoService.loadPreviousData(), turnDto.getTurn()); + StateDto stateDto = daoService.loadPreviousTurn(); + return ChessBoardFactory.loadPreviousChessBoard(daoService.loadPreviousData(), stateDto.getState()); } return ChessBoardFactory.createInitialChessBoard(); } @@ -54,6 +54,6 @@ private void updateGameStatus(final DaoService daoService, final ChessBoard boar return; } daoService.updatePiece(board.getPieces()); - daoService.updateTurn(board.getStatus()); + daoService.updateTurn(StateDto.of(board.getState())); } } diff --git a/src/main/java/controller/command/EndOnCommand.java b/src/main/java/controller/command/EndOnCommand.java index b032fea97cc..62c6d6ed414 100644 --- a/src/main/java/controller/command/EndOnCommand.java +++ b/src/main/java/controller/command/EndOnCommand.java @@ -8,10 +8,6 @@ public class EndOnCommand implements Command { private static final int ARGUMENT_SIZE = 0; - public EndOnCommand() { - this(List.of()); - } - public EndOnCommand(final List arguments) { validateArgumentSize(arguments); } diff --git a/src/main/java/controller/command/MoveOnCommand.java b/src/main/java/controller/command/MoveOnCommand.java index 20d15010a1a..86c78e5cf3d 100644 --- a/src/main/java/controller/command/MoveOnCommand.java +++ b/src/main/java/controller/command/MoveOnCommand.java @@ -1,7 +1,7 @@ package controller.command; import domain.board.ChessBoard; -import domain.board.GameStatus; +import domain.board.State; import domain.position.Position; import view.OutputView; @@ -37,10 +37,10 @@ public void execute(final ChessBoard board, final OutputView outputView) { } private void validateGameStatus(final ChessBoard board) { - if (board.getStatus() == GameStatus.NOT_STARTED) { + if (board.getState() == State.NOT_STARTED) { throw new IllegalStateException("게임을 먼저 시작해 주세요."); } - if (board.getStatus() == GameStatus.ENDED || board.getStatus() == GameStatus.KING_IS_DEAD) { + if (board.getState() == State.ENDED || board.getState() == State.KING_IS_DEAD) { throw new IllegalStateException("게임이 종료됐습니다."); } } diff --git a/src/main/java/controller/command/StartOnCommand.java b/src/main/java/controller/command/StartOnCommand.java index 7f8a0362a41..450f509ed81 100644 --- a/src/main/java/controller/command/StartOnCommand.java +++ b/src/main/java/controller/command/StartOnCommand.java @@ -1,7 +1,7 @@ package controller.command; import domain.board.ChessBoard; -import domain.board.GameStatus; +import domain.board.State; import view.OutputView; import java.util.List; @@ -9,10 +9,6 @@ public class StartOnCommand implements Command { private static final int ARGUMENT_SIZE = 0; - public StartOnCommand() { - this(List.of()); - } - public StartOnCommand(final List arguments) { validateArgumentSize(arguments); } @@ -31,7 +27,7 @@ public void execute(final ChessBoard board, final OutputView outputView) { } private void validateGameStatus(final ChessBoard board) { - if (board.getStatus() != GameStatus.NOT_STARTED) { + if (board.getState() != State.NOT_STARTED) { throw new IllegalStateException("게임이 이미 시작됐습니다."); } } diff --git a/src/main/java/controller/command/StatusOnCommand.java b/src/main/java/controller/command/StatusOnCommand.java index 213b2e5b7cb..9dada14e806 100644 --- a/src/main/java/controller/command/StatusOnCommand.java +++ b/src/main/java/controller/command/StatusOnCommand.java @@ -1,7 +1,7 @@ package controller.command; import domain.board.ChessBoard; -import domain.board.GameStatus; +import domain.board.State; import domain.board.Score; import view.OutputView; @@ -28,10 +28,10 @@ public void execute(final ChessBoard board, final OutputView outputView) { } private void validateGameStatus(final ChessBoard board) { - if (board.getStatus() == GameStatus.NOT_STARTED) { + if (board.getState() == State.NOT_STARTED) { throw new IllegalStateException("게임을 먼저 시작해 주세요."); } - if (board.getStatus() == GameStatus.ENDED || board.getStatus() == GameStatus.KING_IS_DEAD) { + if (board.getState() == State.ENDED || board.getState() == State.KING_IS_DEAD) { throw new IllegalStateException("게임이 종료됐습니다."); } } diff --git a/src/main/java/domain/board/ChessBoard.java b/src/main/java/domain/board/ChessBoard.java index 3260f895850..b7575617b41 100644 --- a/src/main/java/domain/board/ChessBoard.java +++ b/src/main/java/domain/board/ChessBoard.java @@ -15,15 +15,15 @@ public class ChessBoard { private final Map board; - private GameStatus status; + private State state; - public ChessBoard(Map board, GameStatus status) { - this.board = board; - this.status = status; + public ChessBoard(Map board) { + this(new HashMap<>(board), State.NOT_STARTED); } - public ChessBoard(Map board) { - this(new HashMap<>(board), GameStatus.NOT_STARTED); + ChessBoard(Map board, State state) { + this.board = new HashMap<>(board); + this.state = state; } public void move(final Position source, final Position target) { @@ -44,8 +44,8 @@ private void validateEmptyPiece(final Position source) { private void validateTurn(final Position source) { final Piece piece = findPieceByPosition(source); - if (!this.status.isTurnOf(piece.color())) { - throw new IllegalArgumentException(piece.color() + "의 턴입니다."); + if (!this.state.isTurnOf(piece.color())) { + throw new IllegalArgumentException("상대 턴입니다."); } } @@ -72,11 +72,11 @@ private Piece findPieceByPosition(final Position position) { } private void changeTurn() { - if (this.status.isTurnOf(Color.BLACK)) { - this.status = GameStatus.WHITE_TURN; + if (this.state.isTurnOf(Color.BLACK)) { + this.state = State.WHITE_TURN; return; } - this.status = GameStatus.BLACK_TURN; + this.state = State.BLACK_TURN; } public boolean isKingNotExist() { @@ -86,15 +86,15 @@ public boolean isKingNotExist() { } public void start() { - this.status = GameStatus.WHITE_TURN; + this.state = State.WHITE_TURN; } public void end() { - this.status = GameStatus.ENDED; + this.state = State.ENDED; } public boolean isGameRunning() { - return this.status == GameStatus.ENDED; + return this.state == State.ENDED; } public Score calculateScore() { @@ -111,8 +111,7 @@ public List getPieces() { .toList(); } - // TODO: DTO 수정하기 - public GameStatus getStatus() { - return this.status; + public State getState() { + return this.state; } } diff --git a/src/main/java/domain/board/ChessBoardFactory.java b/src/main/java/domain/board/ChessBoardFactory.java index fe316208f36..c215098a853 100644 --- a/src/main/java/domain/board/ChessBoardFactory.java +++ b/src/main/java/domain/board/ChessBoardFactory.java @@ -44,11 +44,11 @@ public static ChessBoard createInitialChessBoard() { return new ChessBoard(pieceMap); } - public static ChessBoard loadPreviousChessBoard(List pieceDtos, final Color color) { + public static ChessBoard loadPreviousChessBoard(List pieceDtos, final State status) { return pieceDtos.stream() .collect(Collectors.collectingAndThen(Collectors.toMap( PieceDto::getPosition, PieceDto::getPiece - ), board -> new ChessBoard(board, color))); + ), board -> new ChessBoard(board, status))); } } diff --git a/src/main/java/domain/board/GameStatus.java b/src/main/java/domain/board/State.java similarity index 84% rename from src/main/java/domain/board/GameStatus.java rename to src/main/java/domain/board/State.java index 841ad354b7f..9bcdb77aa1e 100644 --- a/src/main/java/domain/board/GameStatus.java +++ b/src/main/java/domain/board/State.java @@ -4,7 +4,7 @@ import java.util.function.Function; -public enum GameStatus { +public enum State { NOT_STARTED(color -> false), WHITE_TURN(color -> Color.WHITE == color), BLACK_TURN(color -> Color.BLACK == color), @@ -13,7 +13,7 @@ public enum GameStatus { private final Function isSameTurn; - GameStatus(final Function isSameTurn) { + State(final Function isSameTurn) { this.isSameTurn = isSameTurn; } diff --git a/src/main/java/dto/StateDto.java b/src/main/java/dto/StateDto.java new file mode 100644 index 00000000000..c8ce10ef7ef --- /dev/null +++ b/src/main/java/dto/StateDto.java @@ -0,0 +1,15 @@ +package dto; + +import domain.board.State; + +public record StateDto(String state) { + public static StateDto of(State state) { + return new StateDto( + state.name() + ); + } + + public State getState() { + return State.valueOf(state); + } +} diff --git a/src/main/java/dto/TurnDto.java b/src/main/java/dto/TurnDto.java deleted file mode 100644 index e350c4bca7f..00000000000 --- a/src/main/java/dto/TurnDto.java +++ /dev/null @@ -1,9 +0,0 @@ -package dto; - -import domain.piece.Color; - -public record TurnDto(String color) { - public Color getTurn() { - return Color.valueOf(color); - } -} diff --git a/src/main/java/repository/DaoService.java b/src/main/java/repository/DaoService.java index c3b3143b741..d7502d65701 100644 --- a/src/main/java/repository/DaoService.java +++ b/src/main/java/repository/DaoService.java @@ -2,18 +2,18 @@ import db.JdbcTemplate; import dto.PieceDto; -import dto.TurnDto; +import dto.StateDto; import java.util.List; public class DaoService { private final PieceDao pieceDao; - private final TurnDao turnDao; + private final StateDao stateDao; public DaoService() { final JdbcTemplate jdbcTemplate = new JdbcTemplate(); this.pieceDao = new PieceDao(jdbcTemplate); - this.turnDao = new TurnDao(jdbcTemplate); + this.stateDao = new StateDao(jdbcTemplate); } public boolean isPreviousDataExist() { @@ -24,8 +24,8 @@ public List loadPreviousData() { return pieceDao.findAll(); } - public TurnDto loadPreviousTurn() { - return turnDao.find(); + public StateDto loadPreviousTurn() { + return stateDao.find(); } public void updatePiece(final List pieceDtos) { @@ -35,13 +35,13 @@ public void updatePiece(final List pieceDtos) { } } - public void updateTurn(final TurnDto turnDto) { - turnDao.deleteAll(); - turnDao.update(turnDto); + public void updateTurn(final StateDto stateDto) { + stateDao.deleteAll(); + stateDao.update(stateDto); } public void deletePreviousData() { pieceDao.deleteAll(); - turnDao.deleteAll(); + stateDao.deleteAll(); } } diff --git a/src/main/java/repository/TurnDao.java b/src/main/java/repository/StateDao.java similarity index 58% rename from src/main/java/repository/TurnDao.java rename to src/main/java/repository/StateDao.java index c183f6284ca..b705e95bad8 100644 --- a/src/main/java/repository/TurnDao.java +++ b/src/main/java/repository/StateDao.java @@ -2,28 +2,28 @@ import db.JdbcTemplate; import db.RowMapper; -import dto.TurnDto; +import dto.StateDto; import java.util.List; -public class TurnDao { - private static final String TABLE_NAME = "turns"; +public class StateDao { + private static final String TABLE_NAME = "states"; private final JdbcTemplate jdbcTemplate; - private final RowMapper rowMapper = (resultSet) -> - new TurnDto(resultSet.getString("color")); + private final RowMapper rowMapper = (resultSet) -> + new StateDto(resultSet.getString("state")); - TurnDao() { + StateDao() { this(new JdbcTemplate()); } - TurnDao(final JdbcTemplate jdbcTemplate) { + StateDao(final JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } - TurnDto find() { + StateDto find() { final var query = "SELECT * FROM " + TABLE_NAME + " LIMIT 1"; - final List turns = jdbcTemplate.find(query, rowMapper); + final List turns = jdbcTemplate.find(query, rowMapper); if (turns.isEmpty()) { throw new IllegalArgumentException("데이터가 없습니다."); } @@ -31,14 +31,14 @@ TurnDto find() { } - void update(final TurnDto turnDto) { + void update(final StateDto stateDto) { final String deleteQuery = "DELETE FROM " + TABLE_NAME; - final String insertQuery = "INSERT INTO " + TABLE_NAME + " (color) VALUES (?)"; + final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (?)"; jdbcTemplate.delete(deleteQuery); - jdbcTemplate.add(insertQuery, turnDto.color()); + jdbcTemplate.add(insertQuery, stateDto.state()); } - public void deleteAll() { + void deleteAll() { final String query = "DELETE FROM " + TABLE_NAME; jdbcTemplate.delete(query); } diff --git a/src/main/resources/sql/pieces.sql b/src/main/resources/sql/schema.sql similarity index 71% rename from src/main/resources/sql/pieces.sql rename to src/main/resources/sql/schema.sql index db3702e2216..0ca31ab5704 100644 --- a/src/main/resources/sql/pieces.sql +++ b/src/main/resources/sql/schema.sql @@ -5,4 +5,10 @@ create table pieces color varchar(5) not null, type varchar(6) not null, primary key (board_file, board_rank) +); + +create table states +( + state varchar(15) not null, + primary key (state) ) diff --git a/src/main/resources/sql/turns.sql b/src/main/resources/sql/turns.sql deleted file mode 100644 index 2a0d2f44240..00000000000 --- a/src/main/resources/sql/turns.sql +++ /dev/null @@ -1,5 +0,0 @@ -create table turns -( - color varchar(5) not null, - primary key (color) -) diff --git a/src/test/java/domain/board/ChessBoardTest.java b/src/test/java/domain/board/ChessBoardTest.java index 73b565c6b1f..b1f5f9aa179 100644 --- a/src/test/java/domain/board/ChessBoardTest.java +++ b/src/test/java/domain/board/ChessBoardTest.java @@ -21,7 +21,7 @@ class ChessBoardTest { void 출발_위치에_기물_존재하지_않으면_예외가_발생한다() { Position source = new Position(File.F, Rank.FOUR); Position target = new Position(File.F, Rank.EIGHT); - ChessBoard board = new ChessBoard(Map.of()); + ChessBoard board = new ChessBoard(Map.of(), State.WHITE_TURN); assertThatThrownBy(() -> board.move(source, target)) .isInstanceOf(IllegalArgumentException.class) @@ -35,8 +35,8 @@ class ChessBoardTest { Position between = new Position(File.F, Rank.FIVE); ChessBoard board = new ChessBoard(Map.of( source, new Queen(Color.WHITE), - between, new BlackPawn() - )); + between, new BlackPawn()), + State.WHITE_TURN); assertThatThrownBy(() -> board.move(source, target)) .isInstanceOf(IllegalArgumentException.class) @@ -48,7 +48,7 @@ between, new BlackPawn() Piece piece = new Queen(Color.WHITE); Position source = new Position(File.F, Rank.FOUR); Position target = new Position(File.F, Rank.EIGHT); - ChessBoard board = new ChessBoard(Map.of(source, piece)); + ChessBoard board = new ChessBoard(Map.of(source, piece), State.WHITE_TURN); board.move(source, target); assertThat(board.getBoard()) @@ -63,8 +63,8 @@ between, new BlackPawn() Position target = new Position(File.G, Rank.FIVE); ChessBoard board = new ChessBoard(Map.of( source, piece, - target, new BlackPawn()) - ); + target, new BlackPawn() + ), State.WHITE_TURN); board.move(source, target); assertThat(board.getBoard()) @@ -76,7 +76,9 @@ target, new BlackPawn()) void 게임을_시작하고_피스를_한_번_움직이면_다음은_BLACK_턴이다() { Position resource = new Position(File.F, Rank.FOUR); Position target = new Position(File.F, Rank.EIGHT); - ChessBoard board = new ChessBoard(Map.of(resource, new Queen(Color.WHITE))); + ChessBoard board = new ChessBoard(Map.of(resource, new Queen(Color.WHITE)), State.WHITE_TURN); + + board.start(); board.move(resource, target); assertThatThrownBy(() -> board.move(target, resource)) @@ -92,7 +94,7 @@ target, new BlackPawn()) ChessBoard board = new ChessBoard(Map.of( resource, new Queen(Color.WHITE), between, new BlackPawn() - )); + ), State.WHITE_TURN); assertThatThrownBy(() -> board.move(resource, target)) .isInstanceOf(IllegalArgumentException.class); @@ -109,7 +111,7 @@ between, new BlackPawn() ChessBoard board = new ChessBoard(Map.of( whiteResource, new Queen(Color.WHITE), blackResource, new Queen(Color.BLACK) - )); + ), State.WHITE_TURN); board.move(whiteResource, whiteTarget); board.move(blackResource, blackTarget); diff --git a/src/test/java/repository/DaoServiceTest.java b/src/test/java/repository/DaoServiceTest.java index 1ef351898e0..2d14ffae154 100644 --- a/src/test/java/repository/DaoServiceTest.java +++ b/src/test/java/repository/DaoServiceTest.java @@ -1,8 +1,8 @@ package repository; +import domain.board.State; import dto.PieceDto; -import dto.TurnDto; -import domain.piece.Color; +import dto.StateDto; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -15,10 +15,10 @@ class DaoServiceTest { private static final PieceDto A2WhitePawn = new PieceDto("A", "2", "WHITE", "PAWN"); private static final PieceDto B2WhitePawn = new PieceDto("B", "2", "WHITE", "PAWN"); private static final PieceDto C2WhitePawn = new PieceDto("C", "2", "WHITE", "PAWN"); - private static final TurnDto whiteTurn = new TurnDto("WHITE"); + private static final StateDto whiteTurn = StateDto.of(State.WHITE_TURN); private final PieceDao pieceDao = new PieceDao(); - private final TurnDao turnDao = new TurnDao(); + private final StateDao stateDao = new StateDao(); private final DaoService daoService = new DaoService(); @BeforeEach @@ -26,13 +26,13 @@ void setData() { pieceDao.add(A2WhitePawn); pieceDao.add(B2WhitePawn); pieceDao.add(C2WhitePawn); - turnDao.update(whiteTurn); + stateDao.update(whiteTurn); } @AfterEach void rollback() { pieceDao.deleteAll(); - turnDao.deleteAll(); + stateDao.deleteAll(); } @Test @@ -48,8 +48,8 @@ void rollback() { @Test void 이전_게임의_턴_데이터를_불러온다() { - assertThat(daoService.loadPreviousTurn().getTurn()) - .isEqualTo(Color.WHITE); + assertThat(daoService.loadPreviousTurn().getState()) + .isEqualTo(State.WHITE_TURN); } @Test @@ -68,11 +68,12 @@ void rollback() { @Test void 턴_데이터를_갱신한다() { - TurnDto blackTurn = new TurnDto("BLACK"); + StateDto blackTurn = StateDto.of(State.BLACK_TURN); daoService.updateTurn(blackTurn); - assertThat(daoService.loadPreviousTurn().getTurn()).isEqualTo(Color.BLACK); + assertThat(daoService.loadPreviousTurn().getState()) + .isEqualTo(State.BLACK_TURN); } @Test diff --git a/src/test/java/repository/StateDaoTest.java b/src/test/java/repository/StateDaoTest.java new file mode 100644 index 00000000000..2d4c4fc8c11 --- /dev/null +++ b/src/test/java/repository/StateDaoTest.java @@ -0,0 +1,19 @@ +package repository; + +import domain.board.State; +import dto.StateDto; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class StateDaoTest { + @Test + void 턴을_저장한다() { + StateDto whiteTurn = StateDto.of(State.WHITE_TURN); + StateDao stateDao = new StateDao(); + + stateDao.update(whiteTurn); + + assertThat(stateDao.find().getState()).isEqualTo(State.WHITE_TURN); + } +} diff --git a/src/test/java/repository/TurnDaoTest.java b/src/test/java/repository/TurnDaoTest.java deleted file mode 100644 index 82b3d3f1c58..00000000000 --- a/src/test/java/repository/TurnDaoTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package repository; - -import dto.TurnDto; -import domain.piece.Color; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -class TurnDaoTest { - @Test - void 턴을_저장한다() { - TurnDto whiteTurn = new TurnDto("WHITE"); - TurnDao turnDao = new TurnDao(); - - turnDao.update(whiteTurn); - - assertThat(turnDao.find().getTurn()).isEqualTo(Color.WHITE); - } -} From 29c7961ee109a8749ce19d9fe49c10c3e6313c77 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Fri, 29 Mar 2024 14:51:43 +0900 Subject: [PATCH 43/94] =?UTF-8?q?refactor:=20GameStatus=EB=A5=BC=20State?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/board/ChessBoardTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/domain/board/ChessBoardTest.java b/src/test/java/domain/board/ChessBoardTest.java index b1f5f9aa179..3b6ab36c719 100644 --- a/src/test/java/domain/board/ChessBoardTest.java +++ b/src/test/java/domain/board/ChessBoardTest.java @@ -78,7 +78,6 @@ target, new BlackPawn() Position target = new Position(File.F, Rank.EIGHT); ChessBoard board = new ChessBoard(Map.of(resource, new Queen(Color.WHITE)), State.WHITE_TURN); - board.start(); board.move(resource, target); assertThatThrownBy(() -> board.move(target, resource)) From 8d73e8c4073971701d71b50bd13fd485ddb56f7e Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sat, 30 Mar 2024 18:15:41 +0900 Subject: [PATCH 44/94] =?UTF-8?q?refactor:=20ChessGame=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1,=20=EC=83=81=ED=83=9C=20=ED=8C=A8=ED=84=B4=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/ChessController.java | 55 +++++++---- src/main/java/controller/command/Command.java | 4 +- .../java/controller/command/EndOnCommand.java | 8 +- .../controller/command/MoveOnCommand.java | 23 +---- .../controller/command/StartOnCommand.java | 16 +-- .../controller/command/StatusOnCommand.java | 17 +--- src/main/java/domain/ChessGame.java | 58 +++++++++++ src/main/java/domain/board/ChessBoard.java | 32 ++---- .../java/domain/board/ChessBoardFactory.java | 4 +- src/main/java/domain/board/State.java | 23 ----- src/main/java/domain/piece/Color.java | 4 - src/main/java/domain/state/EndState.java | 23 +++++ src/main/java/domain/state/ReadyState.java | 23 +++++ src/main/java/domain/state/RunningState.java | 23 +++++ src/main/java/domain/state/State.java | 8 ++ src/main/java/dto/StateDto.java | 15 --- src/main/java/dto/TurnDto.java | 16 +++ src/main/java/repository/DaoService.java | 18 ++-- .../{StateDao.java => TurnDao.java} | 22 ++--- src/test/java/domain/ChessGameTest.java | 99 +++++++++++++++++++ .../java/domain/board/ChessBoardTest.java | 16 +-- src/test/java/repository/DaoServiceTest.java | 23 +++-- src/test/java/repository/StateDaoTest.java | 19 ---- src/test/java/repository/TurnDaoTest.java | 19 ++++ 24 files changed, 372 insertions(+), 196 deletions(-) create mode 100644 src/main/java/domain/ChessGame.java delete mode 100644 src/main/java/domain/board/State.java create mode 100644 src/main/java/domain/state/EndState.java create mode 100644 src/main/java/domain/state/ReadyState.java create mode 100644 src/main/java/domain/state/RunningState.java create mode 100644 src/main/java/domain/state/State.java delete mode 100644 src/main/java/dto/StateDto.java create mode 100644 src/main/java/dto/TurnDto.java rename src/main/java/repository/{StateDao.java => TurnDao.java} (61%) create mode 100644 src/test/java/domain/ChessGameTest.java delete mode 100644 src/test/java/repository/StateDaoTest.java create mode 100644 src/test/java/repository/TurnDaoTest.java diff --git a/src/main/java/controller/ChessController.java b/src/main/java/controller/ChessController.java index 1c98717e012..50c0bed7c73 100644 --- a/src/main/java/controller/ChessController.java +++ b/src/main/java/controller/ChessController.java @@ -1,9 +1,9 @@ package controller; -import controller.command.Command; +import domain.ChessGame; import domain.board.ChessBoard; import domain.board.ChessBoardFactory; -import dto.StateDto; +import dto.TurnDto; import repository.DaoService; import view.InputView; import view.OutputView; @@ -19,41 +19,54 @@ public ChessController(InputView inputView, OutputView outputView) { public void start() { DaoService daoService = new DaoService(); - ChessBoard board = createChessBoard(daoService); outputView.printGameGuideMessage(); - Command command; - do { - command = readCommandUntilValid(); - command.execute(board, outputView); - } while (board.isGameRunning()); + ChessGame chessGame = new ChessGame(initializeChessGame(daoService)); - updateGameStatus(daoService, board); + while (chessGame.isPlaying()) { + readCommandUntilValid(chessGame); + } + + updateGameStatus(daoService, chessGame); } - private ChessBoard createChessBoard(DaoService daoService) { - if (daoService.isPreviousDataExist()) { - StateDto stateDto = daoService.loadPreviousTurn(); - return ChessBoardFactory.loadPreviousChessBoard(daoService.loadPreviousData(), stateDto.getState()); + private ChessBoard initializeChessGame(DaoService daoService) { + try { + TurnDto turnDto = daoService.loadPreviousTurn(); + return ChessBoardFactory.loadPreviousChessBoard(daoService.loadPreviousData(), turnDto.getTurn()); + } catch (IllegalArgumentException e) { + return ChessBoardFactory.createInitialChessBoard(); } - return ChessBoardFactory.createInitialChessBoard(); } - private Command readCommandUntilValid() { + private void readCommandUntilValid(ChessGame game) { try { - return inputView.readCommand(); + inputView.readCommand().execute(game, outputView); } catch (Exception e) { outputView.printErrorMessage(e.getMessage()); - return readCommandUntilValid(); + readCommandUntilValid(game); } } - private void updateGameStatus(final DaoService daoService, final ChessBoard board) { - if (board.isKingNotExist()) { + private void updateGameStatus(DaoService daoService, ChessGame game) { + if (game.isGameOver()) { daoService.deletePreviousData(); return; } - daoService.updatePiece(board.getPieces()); - daoService.updateTurn(StateDto.of(board.getState())); + daoService.updatePiece(game.getBoard().getPieces()); + daoService.updateTurn(TurnDto.of(game.getTurn())); } } + + +/* +커넥션을 DAO에 넣어주기 +트랜잭셔널 구현 가능 +테스트도 가능할듯 + +DAO를 테스트하는 이유 +- JDBC를 제대로 썼냐 +- 쿼리를 제대로 썼냐 + + + */ diff --git a/src/main/java/controller/command/Command.java b/src/main/java/controller/command/Command.java index 6d1fb11eb10..801ee91b1a4 100644 --- a/src/main/java/controller/command/Command.java +++ b/src/main/java/controller/command/Command.java @@ -1,8 +1,8 @@ package controller.command; -import domain.board.ChessBoard; +import domain.ChessGame; import view.OutputView; public interface Command { - void execute(ChessBoard board, OutputView outputView); + void execute(ChessGame game, OutputView outputView); } diff --git a/src/main/java/controller/command/EndOnCommand.java b/src/main/java/controller/command/EndOnCommand.java index 62c6d6ed414..e09c115c1dd 100644 --- a/src/main/java/controller/command/EndOnCommand.java +++ b/src/main/java/controller/command/EndOnCommand.java @@ -1,6 +1,6 @@ package controller.command; -import domain.board.ChessBoard; +import domain.ChessGame; import view.OutputView; import java.util.List; @@ -19,8 +19,8 @@ private void validateArgumentSize(final List arguments) { } @Override - public void execute(final ChessBoard board, final OutputView outputView) { - board.end(); - outputView.printScore(board.calculateScore()); + public void execute(final ChessGame game, final OutputView outputView) { + game.end(); + outputView.printScore(game.getScore()); } } diff --git a/src/main/java/controller/command/MoveOnCommand.java b/src/main/java/controller/command/MoveOnCommand.java index 86c78e5cf3d..1c3445ffbe8 100644 --- a/src/main/java/controller/command/MoveOnCommand.java +++ b/src/main/java/controller/command/MoveOnCommand.java @@ -1,7 +1,6 @@ package controller.command; -import domain.board.ChessBoard; -import domain.board.State; +import domain.ChessGame; import domain.position.Position; import view.OutputView; @@ -26,22 +25,8 @@ private void validateArgumentSize(final List arguments) { } @Override - public void execute(final ChessBoard board, final OutputView outputView) { - validateGameStatus(board); - try { - board.move(source, target); - outputView.printBoard(board); - } catch (Exception e) { - outputView.printErrorMessage(e.getMessage()); - } - } - - private void validateGameStatus(final ChessBoard board) { - if (board.getState() == State.NOT_STARTED) { - throw new IllegalStateException("게임을 먼저 시작해 주세요."); - } - if (board.getState() == State.ENDED || board.getState() == State.KING_IS_DEAD) { - throw new IllegalStateException("게임이 종료됐습니다."); - } + public void execute(final ChessGame game, final OutputView outputView) { + game.move(source, target); + outputView.printBoard(game.getBoard()); } } diff --git a/src/main/java/controller/command/StartOnCommand.java b/src/main/java/controller/command/StartOnCommand.java index 450f509ed81..65df16a00e1 100644 --- a/src/main/java/controller/command/StartOnCommand.java +++ b/src/main/java/controller/command/StartOnCommand.java @@ -1,7 +1,6 @@ package controller.command; -import domain.board.ChessBoard; -import domain.board.State; +import domain.ChessGame; import view.OutputView; import java.util.List; @@ -20,15 +19,8 @@ private void validateArgumentSize(final List arguments) { } @Override - public void execute(final ChessBoard board, final OutputView outputView) { - validateGameStatus(board); - board.start(); - outputView.printBoard(board); - } - - private void validateGameStatus(final ChessBoard board) { - if (board.getState() != State.NOT_STARTED) { - throw new IllegalStateException("게임이 이미 시작됐습니다."); - } + public void execute(final ChessGame game, final OutputView outputView) { + game.start(); + outputView.printBoard(game.getBoard()); } } diff --git a/src/main/java/controller/command/StatusOnCommand.java b/src/main/java/controller/command/StatusOnCommand.java index 9dada14e806..488ff9d6ea6 100644 --- a/src/main/java/controller/command/StatusOnCommand.java +++ b/src/main/java/controller/command/StatusOnCommand.java @@ -1,7 +1,6 @@ package controller.command; -import domain.board.ChessBoard; -import domain.board.State; +import domain.ChessGame; import domain.board.Score; import view.OutputView; @@ -21,18 +20,8 @@ private void validateArgumentSize(final List arguments) { } @Override - public void execute(final ChessBoard board, final OutputView outputView) { - validateGameStatus(board); - final Score score = board.calculateScore(); + public void execute(final ChessGame game, final OutputView outputView) { + final Score score = game.getScore(); outputView.printScore(score); } - - private void validateGameStatus(final ChessBoard board) { - if (board.getState() == State.NOT_STARTED) { - throw new IllegalStateException("게임을 먼저 시작해 주세요."); - } - if (board.getState() == State.ENDED || board.getState() == State.KING_IS_DEAD) { - throw new IllegalStateException("게임이 종료됐습니다."); - } - } } diff --git a/src/main/java/domain/ChessGame.java b/src/main/java/domain/ChessGame.java new file mode 100644 index 00000000000..3dcb6baec8f --- /dev/null +++ b/src/main/java/domain/ChessGame.java @@ -0,0 +1,58 @@ +package domain; + +import domain.board.ChessBoard; +import domain.board.Score; +import domain.piece.Color; +import domain.position.Position; +import domain.state.ReadyState; +import domain.state.State; + +public class ChessGame { + private final ChessBoard board; + private State state; + + public ChessGame(final ChessBoard board) { + this(board, new ReadyState()); + } + + private ChessGame(final ChessBoard board, final State state) { + this.board = board; + this.state = state; + } + + public void start() { + this.state = state.start(); + } + + public void move(final Position source, final Position target) { + this.state = state.move(); + board.move(source, target); + if (board.isKingNotExist()) { + this.state = state.end(); + } + } + + public void end() { + state = state.end(); + } + + public boolean isPlaying() { + return state.isPlaying(); + } + + public boolean isGameOver() { + return board.isKingNotExist(); + } + + public Score getScore() { + return board.calculateScore(); + } + + public ChessBoard getBoard() { + return board; + } + + public Color getTurn() { + return board.getTurn(); + } +} diff --git a/src/main/java/domain/board/ChessBoard.java b/src/main/java/domain/board/ChessBoard.java index b7575617b41..3e36782b2d6 100644 --- a/src/main/java/domain/board/ChessBoard.java +++ b/src/main/java/domain/board/ChessBoard.java @@ -15,15 +15,15 @@ public class ChessBoard { private final Map board; - private State state; + private Color turn; public ChessBoard(Map board) { - this(new HashMap<>(board), State.NOT_STARTED); + this(new HashMap<>(board), Color.WHITE); } - ChessBoard(Map board, State state) { + ChessBoard(Map board, Color turn) { this.board = new HashMap<>(board); - this.state = state; + this.turn = turn; } public void move(final Position source, final Position target) { @@ -44,7 +44,7 @@ private void validateEmptyPiece(final Position source) { private void validateTurn(final Position source) { final Piece piece = findPieceByPosition(source); - if (!this.state.isTurnOf(piece.color())) { + if (this.turn != piece.color()) { throw new IllegalArgumentException("상대 턴입니다."); } } @@ -72,11 +72,11 @@ private Piece findPieceByPosition(final Position position) { } private void changeTurn() { - if (this.state.isTurnOf(Color.BLACK)) { - this.state = State.WHITE_TURN; + if (this.turn == Color.BLACK) { + this.turn = Color.WHITE; return; } - this.state = State.BLACK_TURN; + this.turn = Color.BLACK; } public boolean isKingNotExist() { @@ -85,18 +85,6 @@ public boolean isKingNotExist() { .count() != 2; } - public void start() { - this.state = State.WHITE_TURN; - } - - public void end() { - this.state = State.ENDED; - } - - public boolean isGameRunning() { - return this.state == State.ENDED; - } - public Score calculateScore() { return Score.calculate(board); } @@ -111,7 +99,7 @@ public List getPieces() { .toList(); } - public State getState() { - return this.state; + public Color getTurn() { + return this.turn; } } diff --git a/src/main/java/domain/board/ChessBoardFactory.java b/src/main/java/domain/board/ChessBoardFactory.java index c215098a853..70846bd42b6 100644 --- a/src/main/java/domain/board/ChessBoardFactory.java +++ b/src/main/java/domain/board/ChessBoardFactory.java @@ -44,11 +44,11 @@ public static ChessBoard createInitialChessBoard() { return new ChessBoard(pieceMap); } - public static ChessBoard loadPreviousChessBoard(List pieceDtos, final State status) { + public static ChessBoard loadPreviousChessBoard(List pieceDtos, final Color turn) { return pieceDtos.stream() .collect(Collectors.collectingAndThen(Collectors.toMap( PieceDto::getPosition, PieceDto::getPiece - ), board -> new ChessBoard(board, status))); + ), board -> new ChessBoard(board, turn))); } } diff --git a/src/main/java/domain/board/State.java b/src/main/java/domain/board/State.java deleted file mode 100644 index 9bcdb77aa1e..00000000000 --- a/src/main/java/domain/board/State.java +++ /dev/null @@ -1,23 +0,0 @@ -package domain.board; - -import domain.piece.Color; - -import java.util.function.Function; - -public enum State { - NOT_STARTED(color -> false), - WHITE_TURN(color -> Color.WHITE == color), - BLACK_TURN(color -> Color.BLACK == color), - KING_IS_DEAD(color -> false), - ENDED(color -> false); - - private final Function isSameTurn; - - State(final Function isSameTurn) { - this.isSameTurn = isSameTurn; - } - - boolean isTurnOf(final Color color) { - return isSameTurn.apply(color); - } -} diff --git a/src/main/java/domain/piece/Color.java b/src/main/java/domain/piece/Color.java index 31242149623..6232daaba63 100644 --- a/src/main/java/domain/piece/Color.java +++ b/src/main/java/domain/piece/Color.java @@ -12,8 +12,4 @@ public boolean isBlack() { public boolean isNeutrality() { return this == NEUTRALITY; } - - public boolean isOpposite(final Color color) { - return this != color && !color.isNeutrality(); - } } diff --git a/src/main/java/domain/state/EndState.java b/src/main/java/domain/state/EndState.java new file mode 100644 index 00000000000..9de9df6c693 --- /dev/null +++ b/src/main/java/domain/state/EndState.java @@ -0,0 +1,23 @@ +package domain.state; + +public class EndState implements State { + @Override + public State start() { + throw new UnsupportedOperationException("게임이 종료됐습니다."); + } + + @Override + public State move() { + throw new UnsupportedOperationException("게임이 종료됐습니다."); + } + + @Override + public State end() { + throw new UnsupportedOperationException("게임이 종료됐습니다."); + } + + @Override + public boolean isPlaying() { + return false; + } +} diff --git a/src/main/java/domain/state/ReadyState.java b/src/main/java/domain/state/ReadyState.java new file mode 100644 index 00000000000..6d8ce70ea90 --- /dev/null +++ b/src/main/java/domain/state/ReadyState.java @@ -0,0 +1,23 @@ +package domain.state; + +public class ReadyState implements State { + @Override + public State start() { + return new RunningState(); + } + + @Override + public State move() { + throw new UnsupportedOperationException("게임을 시작해 주세요."); + } + + @Override + public State end() { + throw new UnsupportedOperationException("게임을 시작해 주세요."); + } + + @Override + public boolean isPlaying() { + return true; + } +} diff --git a/src/main/java/domain/state/RunningState.java b/src/main/java/domain/state/RunningState.java new file mode 100644 index 00000000000..3033e4da248 --- /dev/null +++ b/src/main/java/domain/state/RunningState.java @@ -0,0 +1,23 @@ +package domain.state; + +public class RunningState implements State { + @Override + public State start() { + throw new UnsupportedOperationException("게임이 이미 시작됐습니다."); + } + + @Override + public State move() { + return this; + } + + @Override + public State end() { + return new EndState(); + } + + @Override + public boolean isPlaying() { + return true; + } +} diff --git a/src/main/java/domain/state/State.java b/src/main/java/domain/state/State.java new file mode 100644 index 00000000000..65d0e908f99 --- /dev/null +++ b/src/main/java/domain/state/State.java @@ -0,0 +1,8 @@ +package domain.state; + +public interface State { + State start(); + State move(); + State end(); + boolean isPlaying(); +} diff --git a/src/main/java/dto/StateDto.java b/src/main/java/dto/StateDto.java deleted file mode 100644 index c8ce10ef7ef..00000000000 --- a/src/main/java/dto/StateDto.java +++ /dev/null @@ -1,15 +0,0 @@ -package dto; - -import domain.board.State; - -public record StateDto(String state) { - public static StateDto of(State state) { - return new StateDto( - state.name() - ); - } - - public State getState() { - return State.valueOf(state); - } -} diff --git a/src/main/java/dto/TurnDto.java b/src/main/java/dto/TurnDto.java new file mode 100644 index 00000000000..71baa44efd7 --- /dev/null +++ b/src/main/java/dto/TurnDto.java @@ -0,0 +1,16 @@ +package dto; + + +import domain.piece.Color; + +public record TurnDto(String turn) { + public static TurnDto of(Color turn) { + return new TurnDto( + turn.name() + ); + } + + public Color getTurn() { + return Color.valueOf(turn); + } +} diff --git a/src/main/java/repository/DaoService.java b/src/main/java/repository/DaoService.java index d7502d65701..c3b3143b741 100644 --- a/src/main/java/repository/DaoService.java +++ b/src/main/java/repository/DaoService.java @@ -2,18 +2,18 @@ import db.JdbcTemplate; import dto.PieceDto; -import dto.StateDto; +import dto.TurnDto; import java.util.List; public class DaoService { private final PieceDao pieceDao; - private final StateDao stateDao; + private final TurnDao turnDao; public DaoService() { final JdbcTemplate jdbcTemplate = new JdbcTemplate(); this.pieceDao = new PieceDao(jdbcTemplate); - this.stateDao = new StateDao(jdbcTemplate); + this.turnDao = new TurnDao(jdbcTemplate); } public boolean isPreviousDataExist() { @@ -24,8 +24,8 @@ public List loadPreviousData() { return pieceDao.findAll(); } - public StateDto loadPreviousTurn() { - return stateDao.find(); + public TurnDto loadPreviousTurn() { + return turnDao.find(); } public void updatePiece(final List pieceDtos) { @@ -35,13 +35,13 @@ public void updatePiece(final List pieceDtos) { } } - public void updateTurn(final StateDto stateDto) { - stateDao.deleteAll(); - stateDao.update(stateDto); + public void updateTurn(final TurnDto turnDto) { + turnDao.deleteAll(); + turnDao.update(turnDto); } public void deletePreviousData() { pieceDao.deleteAll(); - stateDao.deleteAll(); + turnDao.deleteAll(); } } diff --git a/src/main/java/repository/StateDao.java b/src/main/java/repository/TurnDao.java similarity index 61% rename from src/main/java/repository/StateDao.java rename to src/main/java/repository/TurnDao.java index b705e95bad8..c53092a4b66 100644 --- a/src/main/java/repository/StateDao.java +++ b/src/main/java/repository/TurnDao.java @@ -2,28 +2,28 @@ import db.JdbcTemplate; import db.RowMapper; -import dto.StateDto; +import dto.TurnDto; import java.util.List; -public class StateDao { - private static final String TABLE_NAME = "states"; +public class TurnDao { + private static final String TABLE_NAME = "turns"; private final JdbcTemplate jdbcTemplate; - private final RowMapper rowMapper = (resultSet) -> - new StateDto(resultSet.getString("state")); + private final RowMapper rowMapper = (resultSet) -> + new TurnDto(resultSet.getString("turn")); - StateDao() { + TurnDao() { this(new JdbcTemplate()); } - StateDao(final JdbcTemplate jdbcTemplate) { + TurnDao(final JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } - StateDto find() { + TurnDto find() { final var query = "SELECT * FROM " + TABLE_NAME + " LIMIT 1"; - final List turns = jdbcTemplate.find(query, rowMapper); + final List turns = jdbcTemplate.find(query, rowMapper); if (turns.isEmpty()) { throw new IllegalArgumentException("데이터가 없습니다."); } @@ -31,11 +31,11 @@ StateDto find() { } - void update(final StateDto stateDto) { + void update(final TurnDto turnDto) { final String deleteQuery = "DELETE FROM " + TABLE_NAME; final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (?)"; jdbcTemplate.delete(deleteQuery); - jdbcTemplate.add(insertQuery, stateDto.state()); + jdbcTemplate.add(insertQuery, turnDto.turn()); } void deleteAll() { diff --git a/src/test/java/domain/ChessGameTest.java b/src/test/java/domain/ChessGameTest.java new file mode 100644 index 00000000000..13e63c40c20 --- /dev/null +++ b/src/test/java/domain/ChessGameTest.java @@ -0,0 +1,99 @@ +package domain; + +import domain.board.ChessBoard; +import domain.piece.Color; +import domain.piece.nonpawn.King; +import domain.position.Position; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class ChessGameTest { + @Test + void 게임을_시작하기_전에_말을_움직일_수_없다() { + ChessGame game = new ChessGame(new ChessBoard(Map.of())); + + assertThatThrownBy(() -> game.move(new Position("A1"), new Position("A2"))) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessageContaining("게임을 시작해 주세요."); + } + + @Test + void 게임을_시작하기_전에_종료할_수_없다() { + ChessGame game = new ChessGame(new ChessBoard(Map.of())); + + assertThatThrownBy(game::end) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessageContaining("게임을 시작해 주세요."); + } + + @Test + void 게임을_시작하고_다시_시작할_수_없다() { + ChessGame game = new ChessGame(new ChessBoard(Map.of())); + + game.start(); + + assertThatThrownBy(game::start) + .isInstanceOf(UnsupportedOperationException.class) + .hasMessageContaining("게임이 이미 시작됐습니다."); + } + + @Test + void 게임이_생성되기만_하면_게임은_진행_상태이다() { + ChessGame game = new ChessGame(new ChessBoard(Map.of())); + + assertThat(game.isPlaying()).isTrue(); + } + + @Test + void end를_호출하기_전까지_게임은_진행_상태이다() { + ChessGame game = new ChessGame(new ChessBoard(Map.of())); + + game.start(); + + assertThat(game.isPlaying()).isTrue(); + } + + @Test + void end를_호출되면_게임은_종료된다() { + ChessGame game = new ChessGame(new ChessBoard(Map.of())); + + game.start(); + game.end(); + + assertThat(game.isPlaying()).isFalse(); + } + + @Test + void 피스를_움직이고_왕이_죽으면_게임은_오버된다() { + Position A1 = new Position("A1"); + Position A2 = new Position("A2"); + ChessGame game = new ChessGame(new ChessBoard(Map.of( + A1, new King(Color.WHITE), + A2, new King(Color.BLACK)))); + + game.start(); + game.move(A1, A2); + + assertThat(game.isGameOver()).isTrue(); + } + + @Test + void 모든_KING이_살아있으면_게임은_오버되지_않는다() { + ChessGame game = new ChessGame(new ChessBoard(Map.of( + new Position("A1"), new King(Color.WHITE), + new Position("A2"), new King(Color.BLACK)))); + + assertThat(game.isGameOver()).isFalse(); + } + + @Test + void KING이_없으면_게임_오버_상태이다() { + ChessGame game = new ChessGame(new ChessBoard(Map.of())); + + assertThat(game.isGameOver()).isTrue(); + } +} diff --git a/src/test/java/domain/board/ChessBoardTest.java b/src/test/java/domain/board/ChessBoardTest.java index 3b6ab36c719..55558e466e4 100644 --- a/src/test/java/domain/board/ChessBoardTest.java +++ b/src/test/java/domain/board/ChessBoardTest.java @@ -17,11 +17,13 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; class ChessBoardTest { + private static final Color WHITE_TURN = Color.WHITE; + @Test void 출발_위치에_기물_존재하지_않으면_예외가_발생한다() { Position source = new Position(File.F, Rank.FOUR); Position target = new Position(File.F, Rank.EIGHT); - ChessBoard board = new ChessBoard(Map.of(), State.WHITE_TURN); + ChessBoard board = new ChessBoard(Map.of(), WHITE_TURN); assertThatThrownBy(() -> board.move(source, target)) .isInstanceOf(IllegalArgumentException.class) @@ -36,7 +38,7 @@ class ChessBoardTest { ChessBoard board = new ChessBoard(Map.of( source, new Queen(Color.WHITE), between, new BlackPawn()), - State.WHITE_TURN); + WHITE_TURN); assertThatThrownBy(() -> board.move(source, target)) .isInstanceOf(IllegalArgumentException.class) @@ -48,7 +50,7 @@ between, new BlackPawn()), Piece piece = new Queen(Color.WHITE); Position source = new Position(File.F, Rank.FOUR); Position target = new Position(File.F, Rank.EIGHT); - ChessBoard board = new ChessBoard(Map.of(source, piece), State.WHITE_TURN); + ChessBoard board = new ChessBoard(Map.of(source, piece), WHITE_TURN); board.move(source, target); assertThat(board.getBoard()) @@ -64,7 +66,7 @@ between, new BlackPawn()), ChessBoard board = new ChessBoard(Map.of( source, piece, target, new BlackPawn() - ), State.WHITE_TURN); + ), WHITE_TURN); board.move(source, target); assertThat(board.getBoard()) @@ -76,7 +78,7 @@ target, new BlackPawn() void 게임을_시작하고_피스를_한_번_움직이면_다음은_BLACK_턴이다() { Position resource = new Position(File.F, Rank.FOUR); Position target = new Position(File.F, Rank.EIGHT); - ChessBoard board = new ChessBoard(Map.of(resource, new Queen(Color.WHITE)), State.WHITE_TURN); + ChessBoard board = new ChessBoard(Map.of(resource, new Queen(Color.WHITE)), WHITE_TURN); board.move(resource, target); @@ -93,7 +95,7 @@ target, new BlackPawn() ChessBoard board = new ChessBoard(Map.of( resource, new Queen(Color.WHITE), between, new BlackPawn() - ), State.WHITE_TURN); + ), WHITE_TURN); assertThatThrownBy(() -> board.move(resource, target)) .isInstanceOf(IllegalArgumentException.class); @@ -110,7 +112,7 @@ between, new BlackPawn() ChessBoard board = new ChessBoard(Map.of( whiteResource, new Queen(Color.WHITE), blackResource, new Queen(Color.BLACK) - ), State.WHITE_TURN); + ), WHITE_TURN); board.move(whiteResource, whiteTarget); board.move(blackResource, blackTarget); diff --git a/src/test/java/repository/DaoServiceTest.java b/src/test/java/repository/DaoServiceTest.java index 2d14ffae154..ddf8984b64f 100644 --- a/src/test/java/repository/DaoServiceTest.java +++ b/src/test/java/repository/DaoServiceTest.java @@ -1,8 +1,8 @@ package repository; -import domain.board.State; +import domain.piece.Color; import dto.PieceDto; -import dto.StateDto; +import dto.TurnDto; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -15,10 +15,11 @@ class DaoServiceTest { private static final PieceDto A2WhitePawn = new PieceDto("A", "2", "WHITE", "PAWN"); private static final PieceDto B2WhitePawn = new PieceDto("B", "2", "WHITE", "PAWN"); private static final PieceDto C2WhitePawn = new PieceDto("C", "2", "WHITE", "PAWN"); - private static final StateDto whiteTurn = StateDto.of(State.WHITE_TURN); + private static final TurnDto whiteTurn = TurnDto.of(Color.WHITE); + private static final TurnDto blackTurn = TurnDto.of(Color.BLACK); private final PieceDao pieceDao = new PieceDao(); - private final StateDao stateDao = new StateDao(); + private final TurnDao turnDao = new TurnDao(); private final DaoService daoService = new DaoService(); @BeforeEach @@ -26,13 +27,13 @@ void setData() { pieceDao.add(A2WhitePawn); pieceDao.add(B2WhitePawn); pieceDao.add(C2WhitePawn); - stateDao.update(whiteTurn); + turnDao.update(whiteTurn); } @AfterEach void rollback() { pieceDao.deleteAll(); - stateDao.deleteAll(); + turnDao.deleteAll(); } @Test @@ -48,8 +49,8 @@ void rollback() { @Test void 이전_게임의_턴_데이터를_불러온다() { - assertThat(daoService.loadPreviousTurn().getState()) - .isEqualTo(State.WHITE_TURN); + assertThat(daoService.loadPreviousTurn().getTurn()) + .isEqualTo(Color.WHITE); } @Test @@ -68,12 +69,10 @@ void rollback() { @Test void 턴_데이터를_갱신한다() { - StateDto blackTurn = StateDto.of(State.BLACK_TURN); - daoService.updateTurn(blackTurn); - assertThat(daoService.loadPreviousTurn().getState()) - .isEqualTo(State.BLACK_TURN); + assertThat(daoService.loadPreviousTurn().getTurn()) + .isEqualTo(Color.BLACK); } @Test diff --git a/src/test/java/repository/StateDaoTest.java b/src/test/java/repository/StateDaoTest.java deleted file mode 100644 index 2d4c4fc8c11..00000000000 --- a/src/test/java/repository/StateDaoTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package repository; - -import domain.board.State; -import dto.StateDto; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -class StateDaoTest { - @Test - void 턴을_저장한다() { - StateDto whiteTurn = StateDto.of(State.WHITE_TURN); - StateDao stateDao = new StateDao(); - - stateDao.update(whiteTurn); - - assertThat(stateDao.find().getState()).isEqualTo(State.WHITE_TURN); - } -} diff --git a/src/test/java/repository/TurnDaoTest.java b/src/test/java/repository/TurnDaoTest.java new file mode 100644 index 00000000000..04511fa42c9 --- /dev/null +++ b/src/test/java/repository/TurnDaoTest.java @@ -0,0 +1,19 @@ +package repository; + +import domain.piece.Color; +import dto.TurnDto; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class TurnDaoTest { + @Test + void 턴을_저장한다() { + TurnDto whiteTurn = TurnDto.of(Color.WHITE); + TurnDao turnDao = new TurnDao(); + + turnDao.update(whiteTurn); + + assertThat(turnDao.find().getTurn()).isEqualTo(Color.WHITE); + } +} From e580d53ba176e3e9e305a8676b10796838ee9ac9 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sat, 30 Mar 2024 18:25:34 +0900 Subject: [PATCH 45/94] =?UTF-8?q?chore:=20docker=20=EC=BB=A8=ED=85=8C?= =?UTF-8?q?=EC=9D=B4=EB=84=88=20=EC=83=9D=EC=84=B1=20=EC=8B=9C=EC=A0=90?= =?UTF-8?q?=EC=97=90=20=EC=8A=A4=ED=82=A4=EB=A7=88=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EB=90=98=EB=8F=84=EB=A1=9D=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/db/mysql/init/schema.sql | 14 ++++++++++++++ src/main/resources/sql/schema.sql | 14 -------------- 2 files changed, 14 insertions(+), 14 deletions(-) create mode 100644 docker/db/mysql/init/schema.sql delete mode 100644 src/main/resources/sql/schema.sql diff --git a/docker/db/mysql/init/schema.sql b/docker/db/mysql/init/schema.sql new file mode 100644 index 00000000000..668ee2c0e05 --- /dev/null +++ b/docker/db/mysql/init/schema.sql @@ -0,0 +1,14 @@ +create table pieces +( + board_file varchar(1) not null, + board_rank varchar(1) not null, + color varchar(8) not null, + type varchar(8) not null, + primary key (board_file, board_rank) +); + +create table turns +( + turn varchar(8) not null, + primary key (turn) +) diff --git a/src/main/resources/sql/schema.sql b/src/main/resources/sql/schema.sql deleted file mode 100644 index 0ca31ab5704..00000000000 --- a/src/main/resources/sql/schema.sql +++ /dev/null @@ -1,14 +0,0 @@ -create table pieces -( - board_file varchar(1) not null, - board_rank varchar(1) not null, - color varchar(5) not null, - type varchar(6) not null, - primary key (board_file, board_rank) -); - -create table states -( - state varchar(15) not null, - primary key (state) -) From 013c56ebdc0f96f5a0103bd044f399e86d3a3ca6 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sat, 30 Mar 2024 18:30:59 +0900 Subject: [PATCH 46/94] =?UTF-8?q?style:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EB=AA=85=20=ED=8F=AC=EB=A7=B7=20=EB=B3=80=EA=B2=BD=20=EC=96=B4?= =?UTF-8?q?=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/domain/ChessGameTest.java | 4 ++++ src/test/java/domain/board/ChessBoardTest.java | 4 ++++ src/test/java/domain/board/ScoreTest.java | 4 ++++ src/test/java/domain/dto/PieceDtoTest.java | 4 ++++ src/test/java/domain/piece/nonpawn/BishopTest.java | 4 ++++ src/test/java/domain/piece/nonpawn/KingTest.java | 4 ++++ src/test/java/domain/piece/nonpawn/KnightTest.java | 4 ++++ src/test/java/domain/piece/nonpawn/QueenTest.java | 4 ++++ src/test/java/domain/piece/nonpawn/RookTest.java | 4 ++++ src/test/java/domain/piece/pawn/BlackPawnTest.java | 4 ++++ src/test/java/domain/piece/pawn/WhitePawnTest.java | 4 ++++ src/test/java/domain/position/FileTest.java | 4 ++++ src/test/java/domain/position/PositionTest.java | 4 ---- src/test/java/domain/position/RankTest.java | 4 ++++ src/test/java/domain/position/RouteTest.java | 4 ++++ src/test/java/repository/DaoServiceTest.java | 4 ++++ src/test/java/repository/PieceDaoTest.java | 4 ++++ src/test/java/repository/TurnDaoTest.java | 4 ++++ 18 files changed, 68 insertions(+), 4 deletions(-) delete mode 100644 src/test/java/domain/position/PositionTest.java diff --git a/src/test/java/domain/ChessGameTest.java b/src/test/java/domain/ChessGameTest.java index 13e63c40c20..38b0087b916 100644 --- a/src/test/java/domain/ChessGameTest.java +++ b/src/test/java/domain/ChessGameTest.java @@ -4,6 +4,8 @@ import domain.piece.Color; import domain.piece.nonpawn.King; import domain.position.Position; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import java.util.Map; @@ -11,6 +13,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") class ChessGameTest { @Test void 게임을_시작하기_전에_말을_움직일_수_없다() { diff --git a/src/test/java/domain/board/ChessBoardTest.java b/src/test/java/domain/board/ChessBoardTest.java index 55558e466e4..37656cbce5a 100644 --- a/src/test/java/domain/board/ChessBoardTest.java +++ b/src/test/java/domain/board/ChessBoardTest.java @@ -8,6 +8,8 @@ import domain.position.File; import domain.position.Position; import domain.position.Rank; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import java.util.Map; @@ -16,6 +18,8 @@ import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") class ChessBoardTest { private static final Color WHITE_TURN = Color.WHITE; diff --git a/src/test/java/domain/board/ScoreTest.java b/src/test/java/domain/board/ScoreTest.java index 510476dae9d..0fcc539bf7c 100644 --- a/src/test/java/domain/board/ScoreTest.java +++ b/src/test/java/domain/board/ScoreTest.java @@ -9,6 +9,8 @@ import domain.piece.pawn.BlackPawn; import domain.piece.pawn.WhitePawn; import domain.position.Position; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import java.util.Map; @@ -24,6 +26,8 @@ import static domain.piece.Type.ROOK; import static org.assertj.core.api.Assertions.assertThat; +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") class ScoreTest { @Test void 모든_피스가_존재하면_점수는_38점이다() { diff --git a/src/test/java/domain/dto/PieceDtoTest.java b/src/test/java/domain/dto/PieceDtoTest.java index 363978233d2..0b5ed0f8c33 100644 --- a/src/test/java/domain/dto/PieceDtoTest.java +++ b/src/test/java/domain/dto/PieceDtoTest.java @@ -13,11 +13,15 @@ import domain.position.Position; import domain.position.Rank; import dto.PieceDto; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") class PieceDtoTest { @Test void 도메인에서_DTO로_변환한다() { diff --git a/src/test/java/domain/piece/nonpawn/BishopTest.java b/src/test/java/domain/piece/nonpawn/BishopTest.java index 7e6f9c09f07..44f5ea29c1e 100644 --- a/src/test/java/domain/piece/nonpawn/BishopTest.java +++ b/src/test/java/domain/piece/nonpawn/BishopTest.java @@ -7,11 +7,15 @@ import domain.position.File; import domain.position.Position; import domain.position.Rank; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") class BishopTest { private final Piece bishop = new Bishop(Color.WHITE); diff --git a/src/test/java/domain/piece/nonpawn/KingTest.java b/src/test/java/domain/piece/nonpawn/KingTest.java index 2a3fafa4f1c..d73a38edd15 100644 --- a/src/test/java/domain/piece/nonpawn/KingTest.java +++ b/src/test/java/domain/piece/nonpawn/KingTest.java @@ -7,11 +7,15 @@ import domain.position.File; import domain.position.Position; import domain.position.Rank; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") class KingTest { private final Piece king = new King(Color.WHITE); diff --git a/src/test/java/domain/piece/nonpawn/KnightTest.java b/src/test/java/domain/piece/nonpawn/KnightTest.java index 23a1cbfaa14..7de57bb220c 100644 --- a/src/test/java/domain/piece/nonpawn/KnightTest.java +++ b/src/test/java/domain/piece/nonpawn/KnightTest.java @@ -7,11 +7,15 @@ import domain.position.File; import domain.position.Position; import domain.position.Rank; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") class KnightTest { private final Piece knight = new Knight(Color.WHITE); diff --git a/src/test/java/domain/piece/nonpawn/QueenTest.java b/src/test/java/domain/piece/nonpawn/QueenTest.java index 8f78deac82a..480cbd643ba 100644 --- a/src/test/java/domain/piece/nonpawn/QueenTest.java +++ b/src/test/java/domain/piece/nonpawn/QueenTest.java @@ -7,11 +7,15 @@ import domain.position.File; import domain.position.Position; import domain.position.Rank; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") class QueenTest { private final Piece queen = new Queen(Color.WHITE); diff --git a/src/test/java/domain/piece/nonpawn/RookTest.java b/src/test/java/domain/piece/nonpawn/RookTest.java index 48eb6a36767..4e8b1edf1bd 100644 --- a/src/test/java/domain/piece/nonpawn/RookTest.java +++ b/src/test/java/domain/piece/nonpawn/RookTest.java @@ -7,11 +7,15 @@ import domain.position.File; import domain.position.Position; import domain.position.Rank; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") class RookTest { private final Piece rook = new Rook(Color.WHITE); diff --git a/src/test/java/domain/piece/pawn/BlackPawnTest.java b/src/test/java/domain/piece/pawn/BlackPawnTest.java index a016a0234ca..420ae4c35dc 100644 --- a/src/test/java/domain/piece/pawn/BlackPawnTest.java +++ b/src/test/java/domain/piece/pawn/BlackPawnTest.java @@ -5,11 +5,15 @@ import domain.position.File; import domain.position.Position; import domain.position.Rank; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") class BlackPawnTest { private final Piece blackPawn = new BlackPawn(); diff --git a/src/test/java/domain/piece/pawn/WhitePawnTest.java b/src/test/java/domain/piece/pawn/WhitePawnTest.java index c670eeb9f85..317421a19e4 100644 --- a/src/test/java/domain/piece/pawn/WhitePawnTest.java +++ b/src/test/java/domain/piece/pawn/WhitePawnTest.java @@ -5,11 +5,15 @@ import domain.position.File; import domain.position.Position; import domain.position.Rank; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") class WhitePawnTest { private final Piece whitePawn = new WhitePawn(); diff --git a/src/test/java/domain/position/FileTest.java b/src/test/java/domain/position/FileTest.java index 4df3a3a6d6e..662ee0253de 100644 --- a/src/test/java/domain/position/FileTest.java +++ b/src/test/java/domain/position/FileTest.java @@ -1,5 +1,7 @@ package domain.position; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import java.util.List; @@ -7,6 +9,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") class FileTest { @Test void 존재하지_않은_file명을_찾을_경우_예외가_발생한다() { diff --git a/src/test/java/domain/position/PositionTest.java b/src/test/java/domain/position/PositionTest.java deleted file mode 100644 index 1391a1c935c..00000000000 --- a/src/test/java/domain/position/PositionTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package domain.position; - -class PositionTest { -} diff --git a/src/test/java/domain/position/RankTest.java b/src/test/java/domain/position/RankTest.java index e535f626c11..bda4e82d7ba 100644 --- a/src/test/java/domain/position/RankTest.java +++ b/src/test/java/domain/position/RankTest.java @@ -1,5 +1,7 @@ package domain.position; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import java.util.List; @@ -7,6 +9,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") class RankTest { @Test void 존재하지_않은_rank를_찾을_경우_예외가_발생한다() { diff --git a/src/test/java/domain/position/RouteTest.java b/src/test/java/domain/position/RouteTest.java index f101bf449cd..1781870178f 100644 --- a/src/test/java/domain/position/RouteTest.java +++ b/src/test/java/domain/position/RouteTest.java @@ -2,6 +2,8 @@ import domain.piece.Piece; import domain.piece.pawn.WhitePawn; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -11,6 +13,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") class RouteTest { @Nested class 경로_생성 { diff --git a/src/test/java/repository/DaoServiceTest.java b/src/test/java/repository/DaoServiceTest.java index ddf8984b64f..665d8b2fd11 100644 --- a/src/test/java/repository/DaoServiceTest.java +++ b/src/test/java/repository/DaoServiceTest.java @@ -5,12 +5,16 @@ import dto.TurnDto; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") class DaoServiceTest { private static final PieceDto A2WhitePawn = new PieceDto("A", "2", "WHITE", "PAWN"); private static final PieceDto B2WhitePawn = new PieceDto("B", "2", "WHITE", "PAWN"); diff --git a/src/test/java/repository/PieceDaoTest.java b/src/test/java/repository/PieceDaoTest.java index ba2b9721663..e3d50dd2714 100644 --- a/src/test/java/repository/PieceDaoTest.java +++ b/src/test/java/repository/PieceDaoTest.java @@ -2,10 +2,14 @@ import dto.PieceDto; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") public class PieceDaoTest { private final PieceDao pieceDao = new PieceDao(); diff --git a/src/test/java/repository/TurnDaoTest.java b/src/test/java/repository/TurnDaoTest.java index 04511fa42c9..f463120e04a 100644 --- a/src/test/java/repository/TurnDaoTest.java +++ b/src/test/java/repository/TurnDaoTest.java @@ -2,10 +2,14 @@ import domain.piece.Color; import dto.TurnDto; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") class TurnDaoTest { @Test void 턴을_저장한다() { From e09324d7673d71e37585c6fa4cca303e51795179 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sat, 30 Mar 2024 20:06:49 +0900 Subject: [PATCH 47/94] =?UTF-8?q?refactor:=20view=20=EB=A1=9C=EC=A7=81=20s?= =?UTF-8?q?tatic=20=EB=B3=80=EA=B2=BD,=20=EC=98=81=EC=86=8D=ED=99=94=20?= =?UTF-8?q?=EA=B3=84=EC=B8=B5=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=AA=85=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 6 +- src/main/java/controller/ChessController.java | 60 +++++++------------ src/main/java/controller/command/Command.java | 3 +- .../java/controller/command/EndOnCommand.java | 4 +- .../controller/command/MoveOnCommand.java | 4 +- .../controller/command/StartOnCommand.java | 4 +- .../controller/command/StatusOnCommand.java | 4 +- src/main/java/domain/ChessGame.java | 8 +-- ...{DaoService.java => ChessGameService.java} | 6 +- src/main/java/repository/PieceDao.java | 4 +- src/main/java/repository/TurnDao.java | 4 +- src/main/java/view/InputView.java | 17 ++---- src/main/java/view/OutputView.java | 24 ++++---- ...iceTest.java => ChessGameServiceTest.java} | 22 +++---- src/test/java/repository/TurnDaoTest.java | 2 +- 15 files changed, 69 insertions(+), 103 deletions(-) rename src/main/java/repository/{DaoService.java => ChessGameService.java} (91%) rename src/test/java/repository/{DaoServiceTest.java => ChessGameServiceTest.java} (78%) diff --git a/src/main/java/Application.java b/src/main/java/Application.java index ed9b2b5a47d..cc9df9d5376 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,11 +1,9 @@ import controller.ChessController; -import view.InputView; -import view.MessageResolver; -import view.OutputView; +import repository.ChessGameService; public class Application { public static void main(String[] args) { - ChessController chessController = new ChessController(new InputView(), new OutputView(new MessageResolver())); + ChessController chessController = new ChessController(new ChessGameService()); chessController.start(); } } diff --git a/src/main/java/controller/ChessController.java b/src/main/java/controller/ChessController.java index 50c0bed7c73..9e9640744bb 100644 --- a/src/main/java/controller/ChessController.java +++ b/src/main/java/controller/ChessController.java @@ -4,69 +4,51 @@ import domain.board.ChessBoard; import domain.board.ChessBoardFactory; import dto.TurnDto; -import repository.DaoService; +import repository.ChessGameService; import view.InputView; import view.OutputView; public class ChessController { - private final InputView inputView; - private final OutputView outputView; + private final ChessGameService chessGameService; + private ChessGame chessGame; - public ChessController(InputView inputView, OutputView outputView) { - this.inputView = inputView; - this.outputView = outputView; + public ChessController(final ChessGameService chessGameService) { + this.chessGameService = chessGameService; } public void start() { - DaoService daoService = new DaoService(); - - outputView.printGameGuideMessage(); - ChessGame chessGame = new ChessGame(initializeChessGame(daoService)); - + chessGame = new ChessGame(initializeChessGame()); + OutputView.printGameGuideMessage(); while (chessGame.isPlaying()) { - readCommandUntilValid(chessGame); + readCommandUntilValid(); } - - updateGameStatus(daoService, chessGame); + updateGameStatus(); } - private ChessBoard initializeChessGame(DaoService daoService) { + private ChessBoard initializeChessGame() { try { - TurnDto turnDto = daoService.loadPreviousTurn(); - return ChessBoardFactory.loadPreviousChessBoard(daoService.loadPreviousData(), turnDto.getTurn()); + TurnDto turnDto = chessGameService.loadPreviousTurn(); + return ChessBoardFactory.loadPreviousChessBoard(chessGameService.loadPreviousData(), turnDto.getTurn()); } catch (IllegalArgumentException e) { return ChessBoardFactory.createInitialChessBoard(); } } - private void readCommandUntilValid(ChessGame game) { + private void readCommandUntilValid() { try { - inputView.readCommand().execute(game, outputView); + InputView.readCommand().execute(chessGame); } catch (Exception e) { - outputView.printErrorMessage(e.getMessage()); - readCommandUntilValid(game); + OutputView.printErrorMessage(e); + readCommandUntilValid(); } } - private void updateGameStatus(DaoService daoService, ChessGame game) { - if (game.isGameOver()) { - daoService.deletePreviousData(); + private void updateGameStatus() { + if (chessGame.isGameOver()) { + chessGameService.deletePreviousData(); return; } - daoService.updatePiece(game.getBoard().getPieces()); - daoService.updateTurn(TurnDto.of(game.getTurn())); + chessGameService.updatePiece(chessGame.getBoard().getPieces()); + chessGameService.updateTurn(TurnDto.of(chessGame.getTurn())); } } - - -/* -커넥션을 DAO에 넣어주기 -트랜잭셔널 구현 가능 -테스트도 가능할듯 - -DAO를 테스트하는 이유 -- JDBC를 제대로 썼냐 -- 쿼리를 제대로 썼냐 - - - */ diff --git a/src/main/java/controller/command/Command.java b/src/main/java/controller/command/Command.java index 801ee91b1a4..30ef616704d 100644 --- a/src/main/java/controller/command/Command.java +++ b/src/main/java/controller/command/Command.java @@ -1,8 +1,7 @@ package controller.command; import domain.ChessGame; -import view.OutputView; public interface Command { - void execute(ChessGame game, OutputView outputView); + void execute(ChessGame game); } diff --git a/src/main/java/controller/command/EndOnCommand.java b/src/main/java/controller/command/EndOnCommand.java index e09c115c1dd..11bac11e88e 100644 --- a/src/main/java/controller/command/EndOnCommand.java +++ b/src/main/java/controller/command/EndOnCommand.java @@ -19,8 +19,8 @@ private void validateArgumentSize(final List arguments) { } @Override - public void execute(final ChessGame game, final OutputView outputView) { + public void execute(final ChessGame game) { game.end(); - outputView.printScore(game.getScore()); + OutputView.printScore(game.getScore()); } } diff --git a/src/main/java/controller/command/MoveOnCommand.java b/src/main/java/controller/command/MoveOnCommand.java index 1c3445ffbe8..3e8740691d8 100644 --- a/src/main/java/controller/command/MoveOnCommand.java +++ b/src/main/java/controller/command/MoveOnCommand.java @@ -25,8 +25,8 @@ private void validateArgumentSize(final List arguments) { } @Override - public void execute(final ChessGame game, final OutputView outputView) { + public void execute(final ChessGame game) { game.move(source, target); - outputView.printBoard(game.getBoard()); + OutputView.printBoard(game.getBoard()); } } diff --git a/src/main/java/controller/command/StartOnCommand.java b/src/main/java/controller/command/StartOnCommand.java index 65df16a00e1..17f5f67350f 100644 --- a/src/main/java/controller/command/StartOnCommand.java +++ b/src/main/java/controller/command/StartOnCommand.java @@ -19,8 +19,8 @@ private void validateArgumentSize(final List arguments) { } @Override - public void execute(final ChessGame game, final OutputView outputView) { + public void execute(final ChessGame game) { game.start(); - outputView.printBoard(game.getBoard()); + OutputView.printBoard(game.getBoard()); } } diff --git a/src/main/java/controller/command/StatusOnCommand.java b/src/main/java/controller/command/StatusOnCommand.java index 488ff9d6ea6..4ec96cd05b7 100644 --- a/src/main/java/controller/command/StatusOnCommand.java +++ b/src/main/java/controller/command/StatusOnCommand.java @@ -20,8 +20,8 @@ private void validateArgumentSize(final List arguments) { } @Override - public void execute(final ChessGame game, final OutputView outputView) { + public void execute(final ChessGame game) { final Score score = game.getScore(); - outputView.printScore(score); + OutputView.printScore(score); } } diff --git a/src/main/java/domain/ChessGame.java b/src/main/java/domain/ChessGame.java index 3dcb6baec8f..9a580eb47dd 100644 --- a/src/main/java/domain/ChessGame.java +++ b/src/main/java/domain/ChessGame.java @@ -44,10 +44,6 @@ public boolean isGameOver() { return board.isKingNotExist(); } - public Score getScore() { - return board.calculateScore(); - } - public ChessBoard getBoard() { return board; } @@ -55,4 +51,8 @@ public ChessBoard getBoard() { public Color getTurn() { return board.getTurn(); } + + public Score getScore() { + return board.calculateScore(); + } } diff --git a/src/main/java/repository/DaoService.java b/src/main/java/repository/ChessGameService.java similarity index 91% rename from src/main/java/repository/DaoService.java rename to src/main/java/repository/ChessGameService.java index c3b3143b741..5e141b5fa91 100644 --- a/src/main/java/repository/DaoService.java +++ b/src/main/java/repository/ChessGameService.java @@ -6,11 +6,11 @@ import java.util.List; -public class DaoService { +public class ChessGameService { private final PieceDao pieceDao; private final TurnDao turnDao; - public DaoService() { + public ChessGameService() { final JdbcTemplate jdbcTemplate = new JdbcTemplate(); this.pieceDao = new PieceDao(jdbcTemplate); this.turnDao = new TurnDao(jdbcTemplate); @@ -25,7 +25,7 @@ public List loadPreviousData() { } public TurnDto loadPreviousTurn() { - return turnDao.find(); + return turnDao.findOne(); } public void updatePiece(final List pieceDtos) { diff --git a/src/main/java/repository/PieceDao.java b/src/main/java/repository/PieceDao.java index 1a47e84ccea..e34f488ab43 100644 --- a/src/main/java/repository/PieceDao.java +++ b/src/main/java/repository/PieceDao.java @@ -33,7 +33,7 @@ void add(final PieceDto piece) { PieceDto findOne(final String file, final String rank) { final String query = "SELECT * FROM " + TABLE_NAME + " WHERE board_file = ? and board_rank = ? limit 1"; final List pieces = jdbcTemplate.find(query, rowMapper, file, rank); - if (pieces.size() == 0) { + if (pieces.isEmpty()) { throw new IllegalArgumentException("데이터가 없습니다."); } return pieces.get(0); @@ -52,6 +52,6 @@ void deleteAll() { boolean hasRecords() { final String query = "SELECT * FROM " + TABLE_NAME + " LIMIT 1"; final List pieces = jdbcTemplate.find(query, rowMapper); - return pieces.size() != 0; + return !pieces.isEmpty(); } } diff --git a/src/main/java/repository/TurnDao.java b/src/main/java/repository/TurnDao.java index c53092a4b66..f5406d27e82 100644 --- a/src/main/java/repository/TurnDao.java +++ b/src/main/java/repository/TurnDao.java @@ -21,8 +21,8 @@ public class TurnDao { this.jdbcTemplate = jdbcTemplate; } - TurnDto find() { - final var query = "SELECT * FROM " + TABLE_NAME + " LIMIT 1"; + TurnDto findOne() { + final String query = "SELECT * FROM " + TABLE_NAME + " LIMIT 1"; final List turns = jdbcTemplate.find(query, rowMapper); if (turns.isEmpty()) { throw new IllegalArgumentException("데이터가 없습니다."); diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index d7ad96240b0..b2421b0f549 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -8,19 +8,10 @@ public class InputView { public static final String WRONG_COMMAND_ERROR_MESSAGE = "잘못된 형식의 명령어입니다."; - public static final String GAME_NOT_STARTED_ERROR_MESSAGE = "먼저, 게임을 시작해 주세요."; - private final Scanner scanner; + private static final Scanner SCANNER = new Scanner(System.in); - public InputView() { - this.scanner = new Scanner(System.in); - } - -// public Command readStartCommand() { -// return CommandType.getCommand(readCommandInput()); -// } - - public Command readCommand() { + public static Command readCommand() { try { CommandInput input = readCommandInput(); return CommandType.getCommand(input); @@ -29,7 +20,7 @@ public Command readCommand() { } } - private CommandInput readCommandInput() { - return new CommandInput(scanner.nextLine()); + private static CommandInput readCommandInput() { + return new CommandInput(SCANNER.nextLine()); } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 6eae546541a..e4515bd60cf 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -4,27 +4,23 @@ import domain.board.Score; public class OutputView { - private final MessageResolver messageResolver; + private static final MessageResolver messageResolver = new MessageResolver(); - public OutputView(final MessageResolver messageResolver) { - this.messageResolver = messageResolver; - } - - public void printGameGuideMessage() { + public static void printGameGuideMessage() { System.out.println(messageResolver.resolveGameStartMessage()); } - public void printBoard(ChessBoard board) { - String boardRankMessage = messageResolver.resolveBoard(board); - System.out.println(boardRankMessage); - } - - public void printErrorMessage(String errorMessage) { - System.out.println(errorMessage); + public static void printBoard(ChessBoard board) { + String boardMessage = messageResolver.resolveBoard(board); + System.out.println(boardMessage); } - public void printScore(Score score) { + public static void printScore(Score score) { String scoreMessage = messageResolver.resolveScore(score); System.out.println(scoreMessage); } + + public static void printErrorMessage(Exception e) { + System.out.println(e.getMessage()); + } } diff --git a/src/test/java/repository/DaoServiceTest.java b/src/test/java/repository/ChessGameServiceTest.java similarity index 78% rename from src/test/java/repository/DaoServiceTest.java rename to src/test/java/repository/ChessGameServiceTest.java index 665d8b2fd11..72cdb982b6a 100644 --- a/src/test/java/repository/DaoServiceTest.java +++ b/src/test/java/repository/ChessGameServiceTest.java @@ -15,7 +15,7 @@ @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) @SuppressWarnings("NonAsciiCharacters") -class DaoServiceTest { +class ChessGameServiceTest { private static final PieceDto A2WhitePawn = new PieceDto("A", "2", "WHITE", "PAWN"); private static final PieceDto B2WhitePawn = new PieceDto("B", "2", "WHITE", "PAWN"); private static final PieceDto C2WhitePawn = new PieceDto("C", "2", "WHITE", "PAWN"); @@ -24,7 +24,7 @@ class DaoServiceTest { private final PieceDao pieceDao = new PieceDao(); private final TurnDao turnDao = new TurnDao(); - private final DaoService daoService = new DaoService(); + private final ChessGameService chessGameService = new ChessGameService(); @BeforeEach void setData() { @@ -42,18 +42,18 @@ void rollback() { @Test void 이전_게임_데이터가_존재한다() { - assertThat(daoService.isPreviousDataExist()).isTrue(); + assertThat(chessGameService.isPreviousDataExist()).isTrue(); } @Test void 이전_게임_데이터를_불러온다() { - assertThat(daoService.loadPreviousData()) + assertThat(chessGameService.loadPreviousData()) .containsExactlyInAnyOrder(A2WhitePawn, B2WhitePawn, C2WhitePawn); } @Test void 이전_게임의_턴_데이터를_불러온다() { - assertThat(daoService.loadPreviousTurn().getTurn()) + assertThat(chessGameService.loadPreviousTurn().getTurn()) .isEqualTo(Color.WHITE); } @@ -65,24 +65,24 @@ void rollback() { List pieceDtos = List.of(A3WhitePawn, B3WhitePawn, C3WhitePawn); - daoService.updatePiece(pieceDtos); + chessGameService.updatePiece(pieceDtos); - assertThat(daoService.loadPreviousData()) + assertThat(chessGameService.loadPreviousData()) .containsExactlyInAnyOrder(A3WhitePawn, B3WhitePawn, C3WhitePawn); } @Test void 턴_데이터를_갱신한다() { - daoService.updateTurn(blackTurn); + chessGameService.updateTurn(blackTurn); - assertThat(daoService.loadPreviousTurn().getTurn()) + assertThat(chessGameService.loadPreviousTurn().getTurn()) .isEqualTo(Color.BLACK); } @Test void 모든_데이터를_삭제한다() { - daoService.deletePreviousData(); + chessGameService.deletePreviousData(); - assertThat(daoService.isPreviousDataExist()).isFalse(); + assertThat(chessGameService.isPreviousDataExist()).isFalse(); } } diff --git a/src/test/java/repository/TurnDaoTest.java b/src/test/java/repository/TurnDaoTest.java index f463120e04a..26c0eb58777 100644 --- a/src/test/java/repository/TurnDaoTest.java +++ b/src/test/java/repository/TurnDaoTest.java @@ -18,6 +18,6 @@ class TurnDaoTest { turnDao.update(whiteTurn); - assertThat(turnDao.find().getTurn()).isEqualTo(Color.WHITE); + assertThat(turnDao.findOne().getTurn()).isEqualTo(Color.WHITE); } } From 263a083bf7a6f28a13b2c04d2f230ae8aa5c3d88 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sat, 30 Mar 2024 20:32:42 +0900 Subject: [PATCH 48/94] =?UTF-8?q?refactor:=20Position=20=EC=A3=BC=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EC=9E=90=EB=A5=BC=20=EB=B6=80=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EC=9E=90=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/position/Position.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/domain/position/Position.java b/src/main/java/domain/position/Position.java index bef5259024b..de8d6deaf86 100644 --- a/src/main/java/domain/position/Position.java +++ b/src/main/java/domain/position/Position.java @@ -6,17 +6,17 @@ public class Position { private final File file; private final Rank rank; - public Position(final File file, final Rank rank) { - this.file = file; - this.rank = rank; + public Position(final String fileAndRank) { + this(fileAndRank.substring(0, 1), Integer.parseInt(fileAndRank.substring(1))); } - public Position(final String file, final int rank) { + private Position(final String file, final int rank) { this(File.fromName(file), Rank.fromNumber(rank)); } - public Position(final String fileAndRank) { - this(fileAndRank.substring(0, 1), Integer.parseInt(fileAndRank.substring(1))); + public Position(final File file, final Rank rank) { + this.file = file; + this.rank = rank; } public boolean isStraightAt(final Position target) { From fb8f044ccb2d3c8bbfadca19cda57c0f19a47aa6 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sat, 30 Mar 2024 20:46:33 +0900 Subject: [PATCH 49/94] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EA=B0=9C=ED=96=89=20=EC=82=AD=EC=A0=9C,=20?= =?UTF-8?q?=EC=A0=91=EA=B7=BC=20=EC=A0=9C=EC=96=B4=EC=9E=90=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/InputView.java | 3 +-- src/main/java/view/MessageResolver.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index b2421b0f549..0626dc6445c 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -7,9 +7,8 @@ import java.util.Scanner; public class InputView { - public static final String WRONG_COMMAND_ERROR_MESSAGE = "잘못된 형식의 명령어입니다."; - private static final Scanner SCANNER = new Scanner(System.in); + private static final String WRONG_COMMAND_ERROR_MESSAGE = "잘못된 형식의 명령어입니다."; public static Command readCommand() { try { diff --git a/src/main/java/view/MessageResolver.java b/src/main/java/view/MessageResolver.java index 187e1dc4ff5..538508f7340 100644 --- a/src/main/java/view/MessageResolver.java +++ b/src/main/java/view/MessageResolver.java @@ -19,8 +19,8 @@ import static view.command.CommandType.START; public class MessageResolver { - public static final int BOARD_LENGTH = 8; private static final String LINE_SEPARATOR = System.lineSeparator(); + private static final int BOARD_LENGTH = 8; private static final Map PIECE_DISPLAY = Map.of( Type.PAWN, "p", Type.KNIGHT, "n", From 46b248748f9a0b0806f410d653db424b7add0a46 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sat, 30 Mar 2024 22:13:20 +0900 Subject: [PATCH 50/94] =?UTF-8?q?test:=20=EC=98=81=EC=86=8D=EC=84=B1=20ser?= =?UTF-8?q?vice=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=97=90=20=EB=AA=A8?= =?UTF-8?q?=ED=82=B9=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/repository/ChessGameService.java | 5 ++ .../java/repository/ChessGameServiceTest.java | 57 ++++++++++++++++++- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/src/main/java/repository/ChessGameService.java b/src/main/java/repository/ChessGameService.java index 5e141b5fa91..7ed59984769 100644 --- a/src/main/java/repository/ChessGameService.java +++ b/src/main/java/repository/ChessGameService.java @@ -10,6 +10,11 @@ public class ChessGameService { private final PieceDao pieceDao; private final TurnDao turnDao; + ChessGameService(final PieceDao pieceDao, final TurnDao turnDao) { + this.pieceDao = pieceDao; + this.turnDao = turnDao; + } + public ChessGameService() { final JdbcTemplate jdbcTemplate = new JdbcTemplate(); this.pieceDao = new PieceDao(jdbcTemplate); diff --git a/src/test/java/repository/ChessGameServiceTest.java b/src/test/java/repository/ChessGameServiceTest.java index 72cdb982b6a..e56f5cf62db 100644 --- a/src/test/java/repository/ChessGameServiceTest.java +++ b/src/test/java/repository/ChessGameServiceTest.java @@ -1,6 +1,7 @@ package repository; import domain.piece.Color; +import domain.position.Position; import dto.PieceDto; import dto.TurnDto; import org.junit.jupiter.api.AfterEach; @@ -9,7 +10,9 @@ import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; +import java.util.HashMap; import java.util.List; +import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; @@ -22,9 +25,9 @@ class ChessGameServiceTest { private static final TurnDto whiteTurn = TurnDto.of(Color.WHITE); private static final TurnDto blackTurn = TurnDto.of(Color.BLACK); - private final PieceDao pieceDao = new PieceDao(); - private final TurnDao turnDao = new TurnDao(); - private final ChessGameService chessGameService = new ChessGameService(); + private final PieceDao pieceDao = new PieceMockDao(); + private final TurnDao turnDao = new TurnMockDao(); + private final ChessGameService chessGameService = new ChessGameService(pieceDao, turnDao); @BeforeEach void setData() { @@ -85,4 +88,52 @@ void rollback() { assertThat(chessGameService.isPreviousDataExist()).isFalse(); } + + static class PieceMockDao extends PieceDao { + private Map repository = new HashMap<>(); + + void add(final PieceDto piece) { + Position position = new Position(piece.boardFile() + piece.boardRank()); + repository.put(position, piece); + } + + PieceDto findOne(final String file, final String rank) { + Position position = new Position(file + rank); + if (!repository.containsKey(position)) { + throw new IllegalArgumentException("데이터가 없습니다."); + } + return repository.get(position); + } + + List findAll() { + return repository.values().stream().toList(); + } + + void deleteAll() { + repository = new HashMap<>(); + } + + boolean hasRecords() { + return repository.keySet().size() != 0; + } + } + + static class TurnMockDao extends TurnDao { + private Color repository; + + TurnDto findOne() { + if (repository == null) { + throw new IllegalArgumentException("데이터가 없습니다."); + } + return TurnDto.of(repository); + } + + void update(final TurnDto turnDto) { + repository = turnDto.getTurn(); + } + + void deleteAll() { + repository = null; + } + } } From 81bcc6978adfdd8ed4a9edb39d41d1193e3fc5d9 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sat, 30 Mar 2024 22:32:15 +0900 Subject: [PATCH 51/94] =?UTF-8?q?refactor:=20=EB=AA=85=EB=A0=B9=EC=96=B4?= =?UTF-8?q?=20=EC=8B=A4=ED=96=89=20=EA=B2=B0=EA=B3=BC=20=EB=A9=94=EC=8B=9C?= =?UTF-8?q?=EC=A7=80=20=EC=B6=9C=EB=A0=A5=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/command/EndOnCommand.java | 2 -- src/main/java/controller/command/MoveOnCommand.java | 7 +++++++ src/main/java/domain/piece/pawn/PawnPiece.java | 2 +- src/main/java/view/MessageResolver.java | 7 +++++++ src/main/java/view/OutputView.java | 4 ++++ src/test/java/domain/piece/pawn/BlackPawnTest.java | 12 ++++++------ src/test/java/domain/piece/pawn/WhitePawnTest.java | 12 ++++++------ 7 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/main/java/controller/command/EndOnCommand.java b/src/main/java/controller/command/EndOnCommand.java index 11bac11e88e..01c0000f85f 100644 --- a/src/main/java/controller/command/EndOnCommand.java +++ b/src/main/java/controller/command/EndOnCommand.java @@ -1,7 +1,6 @@ package controller.command; import domain.ChessGame; -import view.OutputView; import java.util.List; @@ -21,6 +20,5 @@ private void validateArgumentSize(final List arguments) { @Override public void execute(final ChessGame game) { game.end(); - OutputView.printScore(game.getScore()); } } diff --git a/src/main/java/controller/command/MoveOnCommand.java b/src/main/java/controller/command/MoveOnCommand.java index 3e8740691d8..f2ec4655eeb 100644 --- a/src/main/java/controller/command/MoveOnCommand.java +++ b/src/main/java/controller/command/MoveOnCommand.java @@ -1,6 +1,7 @@ package controller.command; import domain.ChessGame; +import domain.board.Score; import domain.position.Position; import view.OutputView; @@ -28,5 +29,11 @@ private void validateArgumentSize(final List arguments) { public void execute(final ChessGame game) { game.move(source, target); OutputView.printBoard(game.getBoard()); + + if (game.isGameOver()) { + final Score score = game.getScore(); + OutputView.printScore(score); + OutputView.printWinner(score); + } } } diff --git a/src/main/java/domain/piece/pawn/PawnPiece.java b/src/main/java/domain/piece/pawn/PawnPiece.java index fea04d2ff36..c203694428d 100644 --- a/src/main/java/domain/piece/pawn/PawnPiece.java +++ b/src/main/java/domain/piece/pawn/PawnPiece.java @@ -31,7 +31,7 @@ private void validateColorDifference(final Piece other) { private void validateFawnMovement(final Position source, final Position target, final Piece other) { if (!isPawnMovement(source, target, other)) { - throw new IllegalArgumentException("잘못된 방향으로 이동하고 있습니다."); + throw new IllegalArgumentException("잘못된 위치로 이동하고 있습니다."); } } diff --git a/src/main/java/view/MessageResolver.java b/src/main/java/view/MessageResolver.java index 538508f7340..3dd0d34ad90 100644 --- a/src/main/java/view/MessageResolver.java +++ b/src/main/java/view/MessageResolver.java @@ -84,4 +84,11 @@ public String resolveScore(Score score) { String blackScoreMessage = String.format("BLACK 점수: %.1f", score.getBlackScore()); return String.join(LINE_SEPARATOR, whiteScoreMessage, blackScoreMessage); } + + public String resolveWinner(final Score score) { + if (score.getWhiteScore() > score.getBlackScore()) { + return "우승자는 WHITE입니다!"; + } + return "우승자는 BLACK입니다!"; + } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index e4515bd60cf..54fb350bf89 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -20,6 +20,10 @@ public static void printScore(Score score) { System.out.println(scoreMessage); } + public static void printWinner(final Score score) { + System.out.println(messageResolver.resolveWinner(score)); + } + public static void printErrorMessage(Exception e) { System.out.println(e.getMessage()); } diff --git a/src/test/java/domain/piece/pawn/BlackPawnTest.java b/src/test/java/domain/piece/pawn/BlackPawnTest.java index 420ae4c35dc..511f4c03c48 100644 --- a/src/test/java/domain/piece/pawn/BlackPawnTest.java +++ b/src/test/java/domain/piece/pawn/BlackPawnTest.java @@ -35,7 +35,7 @@ class BlackPawnTest { assertThatThrownBy(() -> blackPawn.validateMovement(source, target, other)) .isInstanceOf(IllegalArgumentException.class) - .hasMessage("잘못된 방향으로 이동하고 있습니다."); + .hasMessage("잘못된 위치로 이동하고 있습니다."); } @Test @@ -56,7 +56,7 @@ class BlackPawnTest { assertThatThrownBy(() -> blackPawn.validateMovement(source, target, other)) .isInstanceOf(IllegalArgumentException.class) - .hasMessage("잘못된 방향으로 이동하고 있습니다."); + .hasMessage("잘못된 위치로 이동하고 있습니다."); } @Test @@ -77,7 +77,7 @@ class BlackPawnTest { assertThatThrownBy(() -> blackPawn.validateMovement(source, target, other)) .isInstanceOf(IllegalArgumentException.class) - .hasMessage("잘못된 방향으로 이동하고 있습니다."); + .hasMessage("잘못된 위치로 이동하고 있습니다."); } @Test @@ -88,7 +88,7 @@ class BlackPawnTest { assertThatThrownBy(() -> blackPawn.validateMovement(source, target, other)) .isInstanceOf(IllegalArgumentException.class) - .hasMessage("잘못된 방향으로 이동하고 있습니다."); + .hasMessage("잘못된 위치로 이동하고 있습니다."); } @Test @@ -110,7 +110,7 @@ class BlackPawnTest { assertThatThrownBy(() -> blackPawn.validateMovement(source, target, other)) .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("잘못된 방향으로 이동하고 있습니다."); + .hasMessageContaining("잘못된 위치로 이동하고 있습니다."); } @Test @@ -121,7 +121,7 @@ class BlackPawnTest { assertThatThrownBy(() -> blackPawn.validateMovement(source, target, other)) .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("잘못된 방향으로 이동하고 있습니다."); + .hasMessageContaining("잘못된 위치로 이동하고 있습니다."); } @Test diff --git a/src/test/java/domain/piece/pawn/WhitePawnTest.java b/src/test/java/domain/piece/pawn/WhitePawnTest.java index 317421a19e4..3862de649cf 100644 --- a/src/test/java/domain/piece/pawn/WhitePawnTest.java +++ b/src/test/java/domain/piece/pawn/WhitePawnTest.java @@ -35,7 +35,7 @@ class WhitePawnTest { assertThatThrownBy(() -> whitePawn.validateMovement(source, target, other)) .isInstanceOf(IllegalArgumentException.class) - .hasMessage("잘못된 방향으로 이동하고 있습니다."); + .hasMessage("잘못된 위치로 이동하고 있습니다."); } @Test @@ -56,7 +56,7 @@ class WhitePawnTest { assertThatThrownBy(() -> whitePawn.validateMovement(source, target, other)) .isInstanceOf(IllegalArgumentException.class) - .hasMessage("잘못된 방향으로 이동하고 있습니다."); + .hasMessage("잘못된 위치로 이동하고 있습니다."); } @Test @@ -77,7 +77,7 @@ class WhitePawnTest { assertThatThrownBy(() -> whitePawn.validateMovement(source, target, other)) .isInstanceOf(IllegalArgumentException.class) - .hasMessage("잘못된 방향으로 이동하고 있습니다."); + .hasMessage("잘못된 위치로 이동하고 있습니다."); } @Test @@ -88,7 +88,7 @@ class WhitePawnTest { assertThatThrownBy(() -> whitePawn.validateMovement(source, target, other)) .isInstanceOf(IllegalArgumentException.class) - .hasMessage("잘못된 방향으로 이동하고 있습니다."); + .hasMessage("잘못된 위치로 이동하고 있습니다."); } @Test @@ -110,7 +110,7 @@ class WhitePawnTest { assertThatThrownBy(() -> whitePawn.validateMovement(source, target, other)) .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("잘못된 방향으로 이동하고 있습니다."); + .hasMessageContaining("잘못된 위치로 이동하고 있습니다."); } @Test @@ -121,7 +121,7 @@ class WhitePawnTest { assertThatThrownBy(() -> whitePawn.validateMovement(source, target, other)) .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("잘못된 방향으로 이동하고 있습니다."); + .hasMessageContaining("잘못된 위치로 이동하고 있습니다."); } @Test From 3f0e0b1b2b80965e2c80c42871ad61d3b44abce2 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sat, 30 Mar 2024 22:34:36 +0900 Subject: [PATCH 52/94] =?UTF-8?q?remove:=20gitkeep=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/main/java/.gitkeep diff --git a/src/main/java/.gitkeep b/src/main/java/.gitkeep deleted file mode 100644 index e69de29bb2d..00000000000 From d7a945369485d536a84bded54b57246ae2805d41 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sat, 30 Mar 2024 22:44:25 +0900 Subject: [PATCH 53/94] =?UTF-8?q?refactor:=20JdbcTemplate=EC=97=90=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=EB=90=9C=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/db/JdbcTemplate.java | 16 ++-------------- src/main/java/repository/PieceDao.java | 10 +++++----- src/main/java/repository/TurnDao.java | 8 ++++---- 3 files changed, 11 insertions(+), 23 deletions(-) diff --git a/src/main/java/db/JdbcTemplate.java b/src/main/java/db/JdbcTemplate.java index 272b4ec06cb..d94d5c59c6c 100644 --- a/src/main/java/db/JdbcTemplate.java +++ b/src/main/java/db/JdbcTemplate.java @@ -13,19 +13,7 @@ public JdbcTemplate() { this.connectionManager = new ConnectionManager(); } - public void add(final String query, final String... parameters) { - execute(query, parameters); - } - - public List find(final String query, final RowMapper mapper, final String... parameters) { - return executeAndGet(query, mapper, parameters); - } - - public void delete(final String query, final String... parameters) { - execute(query, parameters); - } - - private void execute(final String query, final String[] parameters) { + public void execute(final String query, final String... parameters) { try (final var connection = connectionManager.getConnection(); final var preparedStatement = connection.prepareStatement(query)) { setParameters(preparedStatement, parameters); @@ -35,7 +23,7 @@ private void execute(final String query, final String[] parameters) { } } - private List executeAndGet(final String query, final RowMapper mapper, final String[] parameters) { + public List executeAndGet(final String query, final RowMapper mapper, final String... parameters) { try (final var connection = connectionManager.getConnection(); final var preparedStatement = connection.prepareStatement(query)) { setParameters(preparedStatement, parameters); diff --git a/src/main/java/repository/PieceDao.java b/src/main/java/repository/PieceDao.java index e34f488ab43..e7def73aada 100644 --- a/src/main/java/repository/PieceDao.java +++ b/src/main/java/repository/PieceDao.java @@ -27,12 +27,12 @@ public class PieceDao { void add(final PieceDto piece) { final String query = "INSERT INTO " + TABLE_NAME + " VALUES(?, ?, ?, ?)"; - jdbcTemplate.add(query, piece.boardFile(), piece.boardRank(), piece.color(), piece.type()); + jdbcTemplate.execute(query, piece.boardFile(), piece.boardRank(), piece.color(), piece.type()); } PieceDto findOne(final String file, final String rank) { final String query = "SELECT * FROM " + TABLE_NAME + " WHERE board_file = ? and board_rank = ? limit 1"; - final List pieces = jdbcTemplate.find(query, rowMapper, file, rank); + final List pieces = jdbcTemplate.executeAndGet(query, rowMapper, file, rank); if (pieces.isEmpty()) { throw new IllegalArgumentException("데이터가 없습니다."); } @@ -41,17 +41,17 @@ PieceDto findOne(final String file, final String rank) { List findAll() { final String query = "SELECT * FROM " + TABLE_NAME; - return jdbcTemplate.find(query, rowMapper); + return jdbcTemplate.executeAndGet(query, rowMapper); } void deleteAll() { final String query = "DELETE FROM " + TABLE_NAME; - jdbcTemplate.delete(query); + jdbcTemplate.execute(query); } boolean hasRecords() { final String query = "SELECT * FROM " + TABLE_NAME + " LIMIT 1"; - final List pieces = jdbcTemplate.find(query, rowMapper); + final List pieces = jdbcTemplate.executeAndGet(query, rowMapper); return !pieces.isEmpty(); } } diff --git a/src/main/java/repository/TurnDao.java b/src/main/java/repository/TurnDao.java index f5406d27e82..b8078c0212c 100644 --- a/src/main/java/repository/TurnDao.java +++ b/src/main/java/repository/TurnDao.java @@ -23,7 +23,7 @@ public class TurnDao { TurnDto findOne() { final String query = "SELECT * FROM " + TABLE_NAME + " LIMIT 1"; - final List turns = jdbcTemplate.find(query, rowMapper); + final List turns = jdbcTemplate.executeAndGet(query, rowMapper); if (turns.isEmpty()) { throw new IllegalArgumentException("데이터가 없습니다."); } @@ -34,12 +34,12 @@ TurnDto findOne() { void update(final TurnDto turnDto) { final String deleteQuery = "DELETE FROM " + TABLE_NAME; final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (?)"; - jdbcTemplate.delete(deleteQuery); - jdbcTemplate.add(insertQuery, turnDto.turn()); + jdbcTemplate.execute(deleteQuery); + jdbcTemplate.execute(insertQuery, turnDto.turn()); } void deleteAll() { final String query = "DELETE FROM " + TABLE_NAME; - jdbcTemplate.delete(query); + jdbcTemplate.execute(query); } } From d7f52e23f39455127f3e72c4cba2a15729976bd2 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sun, 31 Mar 2024 01:51:23 +0900 Subject: [PATCH 54/94] =?UTF-8?q?style:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EA=B0=9C=ED=96=89=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/repository/TurnDao.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/repository/TurnDao.java b/src/main/java/repository/TurnDao.java index b8078c0212c..0d5bb26caad 100644 --- a/src/main/java/repository/TurnDao.java +++ b/src/main/java/repository/TurnDao.java @@ -30,7 +30,6 @@ TurnDto findOne() { return turns.get(0); } - void update(final TurnDto turnDto) { final String deleteQuery = "DELETE FROM " + TABLE_NAME; final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (?)"; From 8ff370c2ac83fce0519c458b8a58220798e567a1 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sun, 31 Mar 2024 12:38:12 +0900 Subject: [PATCH 55/94] =?UTF-8?q?docs:=20=EC=B6=94=EA=B0=80=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A51=20=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 4af28f6c9ef..fc5e2cde7c2 100644 --- a/README.md +++ b/README.md @@ -141,3 +141,16 @@ - [x] 게임 데이터 갱신 (피스들, 턴) - [x] 이전 게임 데이터 삭제 - [x] 현재 게임 데이터 저장 + +### 추가 기능 1: 체스 게임방을 만들고 체스 게임방에 입장할 수 있는 기능을 추가한다. + +- [ ] 존재하는 모든 게임방 번호를 조회한다. + - [ ] 종료된 게임은 제외한다. +- [ ] 입장할 게임방 번호를 입력 받는다. + - [ ] new를 입력하면 새로운 방을 생성한다. + - **[예외]** 종료된 게임방 번호 + - **[예외]** 존재하지 않는 게임방 번호 +- [ ] 게임을 생성한다. (턴, 피스들) + - [ ] 기존 데이터를 불러오기 + - [ ] 새로 생성하기 +- [ ] end를 입력하면 게임 데이터를 저장한다. From 7e64983ca318e42100eafd8a44f11169a43b3633 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sun, 31 Mar 2024 12:39:22 +0900 Subject: [PATCH 56/94] =?UTF-8?q?feat:=20room=20=EC=8A=A4=ED=82=A4?= =?UTF-8?q?=EB=A7=88=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/db/mysql/init/schema.sql | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/docker/db/mysql/init/schema.sql b/docker/db/mysql/init/schema.sql index 668ee2c0e05..0fe2871cd09 100644 --- a/docker/db/mysql/init/schema.sql +++ b/docker/db/mysql/init/schema.sql @@ -1,14 +1,24 @@ +create table rooms +( + room_id int, + primary key (room_id) +); + +create table game_states +( + game_id int, + state varchar(8) not null, + primary key (game_id), + foreign key (game_id) references rooms (room_id) +); + create table pieces ( board_file varchar(1) not null, board_rank varchar(1) not null, color varchar(8) not null, type varchar(8) not null, - primary key (board_file, board_rank) + game_id int, + primary key (board_file, board_rank), + foreign key (game_id) references rooms (room_id) ); - -create table turns -( - turn varchar(8) not null, - primary key (turn) -) From d023be2224f10b0937988096f3f6c69208e89657 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sun, 31 Mar 2024 12:52:23 +0900 Subject: [PATCH 57/94] =?UTF-8?q?feat:=20RoomDao=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/dto/RoomDto.java | 4 ++ src/main/java/dto/TurnDto.java | 5 ++- src/main/java/repository/RoomDao.java | 52 +++++++++++++++++++++++ src/main/java/repository/TurnDao.java | 13 ++++-- src/test/java/repository/RoomDaoTest.java | 37 ++++++++++++++++ 5 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 src/main/java/dto/RoomDto.java create mode 100644 src/main/java/repository/RoomDao.java create mode 100644 src/test/java/repository/RoomDaoTest.java diff --git a/src/main/java/dto/RoomDto.java b/src/main/java/dto/RoomDto.java new file mode 100644 index 00000000000..0da5e418f65 --- /dev/null +++ b/src/main/java/dto/RoomDto.java @@ -0,0 +1,4 @@ +package dto; + +public record RoomDto(int room_id) { +} diff --git a/src/main/java/dto/TurnDto.java b/src/main/java/dto/TurnDto.java index 71baa44efd7..c7f9cd31bb4 100644 --- a/src/main/java/dto/TurnDto.java +++ b/src/main/java/dto/TurnDto.java @@ -3,10 +3,11 @@ import domain.piece.Color; -public record TurnDto(String turn) { +public record TurnDto(String turn, String gameId) { public static TurnDto of(Color turn) { return new TurnDto( - turn.name() + turn.name(), + null ); } diff --git a/src/main/java/repository/RoomDao.java b/src/main/java/repository/RoomDao.java new file mode 100644 index 00000000000..1fb6eb587fe --- /dev/null +++ b/src/main/java/repository/RoomDao.java @@ -0,0 +1,52 @@ +package repository; + +import db.JdbcTemplate; +import db.RowMapper; +import dto.RoomDto; + +import java.util.List; +import java.util.Optional; + +public class RoomDao { + private static final String TABLE_NAME = "rooms"; + private static final String GAME_STATUES_TABLE_NAME = "game_states"; + + private final JdbcTemplate jdbcTemplate; + private final RowMapper rowMapper = (resultSet) -> new RoomDto( + resultSet.getInt("room_id") + ); + + RoomDao() { + this(new JdbcTemplate()); + } + + RoomDao(final JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + public void add(final RoomDto roomDto) { + final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (?)"; + jdbcTemplate.execute(insertQuery, "" + roomDto.room_id()); + } + + public Optional addNewRoom() { + final String selectQuery = "SELECT MAX(room_id) AS room_id FROM " + TABLE_NAME; + List roomDtos = jdbcTemplate.executeAndGet(selectQuery, rowMapper); + final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (?)"; + final String roodId = String.valueOf(roomDtos.get(0).room_id() + 1); + jdbcTemplate.execute(insertQuery, roodId); + return Optional.ofNullable(roomDtos.get(0)); + } + + public Optional find(final String roomId) { + final String query = "SELECT * FROM " + TABLE_NAME + " WHERE room_id = ?"; + List roomDtos = jdbcTemplate.executeAndGet(query, rowMapper, roomId); + return Optional.of(roomDtos.get(0)); + } + + public List findActiveRoomAll() { + final String query = "SELECT * FROM " + TABLE_NAME + " AS r JOIN " + + GAME_STATUES_TABLE_NAME + " AS s ON r.room_id = s.game_id WHERE s.state != 'GAMEOVER'"; + return jdbcTemplate.executeAndGet(query, rowMapper); + } +} diff --git a/src/main/java/repository/TurnDao.java b/src/main/java/repository/TurnDao.java index 0d5bb26caad..0b428cf2224 100644 --- a/src/main/java/repository/TurnDao.java +++ b/src/main/java/repository/TurnDao.java @@ -7,11 +7,13 @@ import java.util.List; public class TurnDao { - private static final String TABLE_NAME = "turns"; + private static final String TABLE_NAME = "game_states"; private final JdbcTemplate jdbcTemplate; - private final RowMapper rowMapper = (resultSet) -> - new TurnDto(resultSet.getString("turn")); + private final RowMapper rowMapper = (resultSet) -> new TurnDto( + resultSet.getString("state"), + resultSet.getString("game_id") + ); TurnDao() { this(new JdbcTemplate()); @@ -21,6 +23,11 @@ public class TurnDao { this.jdbcTemplate = jdbcTemplate; } + void add(TurnDto turnDto) { + final String query = "INSERT INTO " + TABLE_NAME + " VALUES (?, ?)"; + jdbcTemplate.execute(query, turnDto.turn(), turnDto.gameId()); + } + TurnDto findOne() { final String query = "SELECT * FROM " + TABLE_NAME + " LIMIT 1"; final List turns = jdbcTemplate.executeAndGet(query, rowMapper); diff --git a/src/test/java/repository/RoomDaoTest.java b/src/test/java/repository/RoomDaoTest.java new file mode 100644 index 00000000000..ca876a88847 --- /dev/null +++ b/src/test/java/repository/RoomDaoTest.java @@ -0,0 +1,37 @@ +package repository; + +import dto.RoomDto; +import dto.TurnDto; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") +class RoomDaoTest { + private final RoomDao roomDao = new RoomDao(); + private final TurnDao turnDao = new TurnDao(); + + @Test + void 새로운_방_번호를_생성한다() { + assertThat(roomDao.addNewRoom().isPresent()).isTrue(); + } + + @Test + void 활성화된_방을_모두_찾는다() { + roomDao.add(new RoomDto(1)); + roomDao.add(new RoomDto(2)); + roomDao.add(new RoomDto(3)); + turnDao.add(new TurnDto("WHITE", "1")); + turnDao.add(new TurnDto("GAMEOVER", "2")); + turnDao.add(new TurnDto("BLACK", "3")); + + List activeRoomAll = roomDao.findActiveRoomAll(); + + assertThat(activeRoomAll).containsExactlyInAnyOrder(new RoomDto(1), new RoomDto(3)); + } +} From 5a02d855cbfce76b6e7b8315afb9b76d1b55af08 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sun, 31 Mar 2024 15:39:19 +0900 Subject: [PATCH 58/94] =?UTF-8?q?feat:=20GameRoomService=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/repository/GameRoomService.java | 34 ++++++ .../java/repository/GameRoomServiceTest.java | 101 ++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 src/main/java/repository/GameRoomService.java create mode 100644 src/test/java/repository/GameRoomServiceTest.java diff --git a/src/main/java/repository/GameRoomService.java b/src/main/java/repository/GameRoomService.java new file mode 100644 index 00000000000..72650ec71a4 --- /dev/null +++ b/src/main/java/repository/GameRoomService.java @@ -0,0 +1,34 @@ +package repository; + +import db.JdbcTemplate; +import dto.RoomDto; + +import java.util.List; +import java.util.Optional; + +public class GameRoomService { + private final RoomDao roomDao; + + GameRoomService(final RoomDao roomDao) { + this.roomDao = roomDao; + } + + public GameRoomService() { + final JdbcTemplate jdbcTemplate = new JdbcTemplate(); + this.roomDao = new RoomDao(jdbcTemplate); + } + + public List loadActiveRoomAll() { + return roomDao.findActiveRoomAll(); + } + + public RoomDto createNewRoom() { + Optional room = roomDao.addNewRoom(); + return room.orElseThrow(IllegalStateException::new); + } + + public RoomDto findRoomById(final String roomId) { + Optional room = roomDao.find(roomId); + return room.orElseThrow(IllegalArgumentException::new); + } +} diff --git a/src/test/java/repository/GameRoomServiceTest.java b/src/test/java/repository/GameRoomServiceTest.java new file mode 100644 index 00000000000..bea6852c44c --- /dev/null +++ b/src/test/java/repository/GameRoomServiceTest.java @@ -0,0 +1,101 @@ +package repository; + +import dto.RoomDto; +import dto.TurnDto; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") +class GameRoomServiceTest { + private final RoomDto room1 = new RoomDto(1); + private final RoomDto room2 = new RoomDto(2); + private final RoomDto room3 = new RoomDto(3); + + private final Map roomRepository = Map.of( + room1.room_id(), room1, + room2.room_id(), room2, + room3.room_id(), room3); + + private final Map turnRepository = Map.of( + room1.room_id(), new TurnDto("GAMEOVER", String.valueOf(room1.room_id())), + room2.room_id(), new TurnDto("WHITE", String.valueOf(room2.room_id())), + room3.room_id(), new TurnDto("BLACK", String.valueOf(room3.room_id()))); + + @Test + void 활성화된_모든_방을_불러온다() { + RoomDao roomDao = new RoomMockDao(roomRepository, turnRepository); + GameRoomService gameRoomService = new GameRoomService(roomDao); + + assertThat(gameRoomService.loadActiveRoomAll()) + .containsExactlyInAnyOrder(room2, room3); + } + + @Test + void ID로_방을_찾는다() { + RoomDao roomDao = new RoomMockDao(roomRepository, turnRepository); + GameRoomService gameRoomService = new GameRoomService(roomDao); + + RoomDto findRoom = gameRoomService.findRoomById("1"); + + assertThat(findRoom).isEqualTo(room1); + } + + @Test + void 새로운_방을_만든다() { + RoomDao roomDao = new RoomMockDao(new HashMap<>(), new HashMap<>()); + GameRoomService gameRoomService = new GameRoomService(roomDao); + + assertThatCode(gameRoomService::createNewRoom) + .doesNotThrowAnyException(); + } + + static class RoomMockDao extends RoomDao { + private final Map roomRepository; + private final Map turnRepository; + + public RoomMockDao(Map roomRepository, Map turnRepository) { + this.roomRepository = roomRepository; + this.turnRepository = turnRepository; + } + + public void add(final RoomDto roomDto) { + roomRepository.put(roomDto.room_id(), roomDto); + } + + public Optional addNewRoom() { + if (roomRepository.keySet().isEmpty()) { + RoomDto newRoomDto = new RoomDto(1); + roomRepository.put(newRoomDto.room_id(), newRoomDto); + return Optional.of(newRoomDto); + } + + int newRoomId = Collections.max(roomRepository.keySet()) + 1; + RoomDto newRoomDto = new RoomDto(newRoomId); + roomRepository.put(newRoomDto.room_id(), newRoomDto); + return Optional.of(newRoomDto); + } + + public Optional find(final String roomId) { + return Optional.of(roomRepository.get(Integer.parseInt(roomId))); + } + + public List findActiveRoomAll() { + return roomRepository.keySet().stream() + .filter(roomId -> !Objects.equals(turnRepository.get(roomId).turn(), "GAMEOVER")) + .map(roomRepository::get) + .toList(); + } + } +} From bd5cf95a20d422511f74ec46202e2bc0cb9336bf Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sun, 31 Mar 2024 16:05:50 +0900 Subject: [PATCH 59/94] =?UTF-8?q?refactor:=20DTO=20=ED=95=84=EB=93=9C=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/dto/TurnDto.java | 9 +----- .../java/repository/ChessGameService.java | 5 +-- src/main/java/repository/TurnDao.java | 13 ++++---- .../java/repository/ChessGameServiceTest.java | 32 +++++++++++-------- .../java/repository/GameRoomServiceTest.java | 6 ++-- src/test/java/repository/RoomDaoTest.java | 6 ++-- src/test/java/repository/TurnDaoTest.java | 6 ++-- 7 files changed, 40 insertions(+), 37 deletions(-) diff --git a/src/main/java/dto/TurnDto.java b/src/main/java/dto/TurnDto.java index c7f9cd31bb4..ff5581f968b 100644 --- a/src/main/java/dto/TurnDto.java +++ b/src/main/java/dto/TurnDto.java @@ -3,14 +3,7 @@ import domain.piece.Color; -public record TurnDto(String turn, String gameId) { - public static TurnDto of(Color turn) { - return new TurnDto( - turn.name(), - null - ); - } - +public record TurnDto(String turn, int gameId) { public Color getTurn() { return Color.valueOf(turn); } diff --git a/src/main/java/repository/ChessGameService.java b/src/main/java/repository/ChessGameService.java index 7ed59984769..ba7f02d535f 100644 --- a/src/main/java/repository/ChessGameService.java +++ b/src/main/java/repository/ChessGameService.java @@ -2,6 +2,7 @@ import db.JdbcTemplate; import dto.PieceDto; +import dto.RoomDto; import dto.TurnDto; import java.util.List; @@ -29,8 +30,8 @@ public List loadPreviousData() { return pieceDao.findAll(); } - public TurnDto loadPreviousTurn() { - return turnDao.findOne(); + public TurnDto loadPreviousTurn(final RoomDto roomDto) { + return turnDao.findTurnByGameId(roomDto); } public void updatePiece(final List pieceDtos) { diff --git a/src/main/java/repository/TurnDao.java b/src/main/java/repository/TurnDao.java index 0b428cf2224..281bbd6ef66 100644 --- a/src/main/java/repository/TurnDao.java +++ b/src/main/java/repository/TurnDao.java @@ -2,6 +2,7 @@ import db.JdbcTemplate; import db.RowMapper; +import dto.RoomDto; import dto.TurnDto; import java.util.List; @@ -12,7 +13,7 @@ public class TurnDao { private final JdbcTemplate jdbcTemplate; private final RowMapper rowMapper = (resultSet) -> new TurnDto( resultSet.getString("state"), - resultSet.getString("game_id") + resultSet.getInt("game_id") ); TurnDao() { @@ -23,14 +24,14 @@ public class TurnDao { this.jdbcTemplate = jdbcTemplate; } - void add(TurnDto turnDto) { + void add(final TurnDto turnDto) { final String query = "INSERT INTO " + TABLE_NAME + " VALUES (?, ?)"; - jdbcTemplate.execute(query, turnDto.turn(), turnDto.gameId()); + jdbcTemplate.execute(query, turnDto.turn(), String.valueOf(turnDto.gameId())); } - TurnDto findOne() { - final String query = "SELECT * FROM " + TABLE_NAME + " LIMIT 1"; - final List turns = jdbcTemplate.executeAndGet(query, rowMapper); + TurnDto findTurnByGameId(final RoomDto roomDto) { + final String query = "SELECT * FROM " + TABLE_NAME + " WHERE game_id = ?"; + final List turns = jdbcTemplate.executeAndGet(query, rowMapper, String.valueOf(roomDto.room_id())); if (turns.isEmpty()) { throw new IllegalArgumentException("데이터가 없습니다."); } diff --git a/src/test/java/repository/ChessGameServiceTest.java b/src/test/java/repository/ChessGameServiceTest.java index e56f5cf62db..5327d6f06d8 100644 --- a/src/test/java/repository/ChessGameServiceTest.java +++ b/src/test/java/repository/ChessGameServiceTest.java @@ -3,6 +3,7 @@ import domain.piece.Color; import domain.position.Position; import dto.PieceDto; +import dto.RoomDto; import dto.TurnDto; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -22,8 +23,8 @@ class ChessGameServiceTest { private static final PieceDto A2WhitePawn = new PieceDto("A", "2", "WHITE", "PAWN"); private static final PieceDto B2WhitePawn = new PieceDto("B", "2", "WHITE", "PAWN"); private static final PieceDto C2WhitePawn = new PieceDto("C", "2", "WHITE", "PAWN"); - private static final TurnDto whiteTurn = TurnDto.of(Color.WHITE); - private static final TurnDto blackTurn = TurnDto.of(Color.BLACK); + private static final TurnDto whiteTurn = new TurnDto("WHITE", 1); + private static final TurnDto blackTurn = new TurnDto("BLACK", 2); private final PieceDao pieceDao = new PieceMockDao(); private final TurnDao turnDao = new TurnMockDao(); @@ -56,7 +57,9 @@ void rollback() { @Test void 이전_게임의_턴_데이터를_불러온다() { - assertThat(chessGameService.loadPreviousTurn().getTurn()) + RoomDto roomDto = new RoomDto(1); + + assertThat(chessGameService.loadPreviousTurn(roomDto).getTurn()) .isEqualTo(Color.WHITE); } @@ -76,9 +79,11 @@ void rollback() { @Test void 턴_데이터를_갱신한다() { + RoomDto room = new RoomDto(blackTurn.gameId()); + chessGameService.updateTurn(blackTurn); - assertThat(chessGameService.loadPreviousTurn().getTurn()) + assertThat(chessGameService.loadPreviousTurn(room).getTurn()) .isEqualTo(Color.BLACK); } @@ -118,22 +123,23 @@ boolean hasRecords() { } } + static class TurnMockDao extends TurnDao { - private Color repository; + private final Map repository = new HashMap<>(); + + void add(TurnDto turnDto) { + repository.put(turnDto.gameId(), turnDto); + } - TurnDto findOne() { - if (repository == null) { + TurnDto findTurnByGameId(RoomDto roomDto) { + if (!repository.containsKey(roomDto.room_id())) { throw new IllegalArgumentException("데이터가 없습니다."); } - return TurnDto.of(repository); + return repository.get(roomDto.room_id()); } void update(final TurnDto turnDto) { - repository = turnDto.getTurn(); - } - - void deleteAll() { - repository = null; + repository.put(turnDto.gameId(), turnDto); } } } diff --git a/src/test/java/repository/GameRoomServiceTest.java b/src/test/java/repository/GameRoomServiceTest.java index bea6852c44c..ae46bef2bda 100644 --- a/src/test/java/repository/GameRoomServiceTest.java +++ b/src/test/java/repository/GameRoomServiceTest.java @@ -29,9 +29,9 @@ class GameRoomServiceTest { room3.room_id(), room3); private final Map turnRepository = Map.of( - room1.room_id(), new TurnDto("GAMEOVER", String.valueOf(room1.room_id())), - room2.room_id(), new TurnDto("WHITE", String.valueOf(room2.room_id())), - room3.room_id(), new TurnDto("BLACK", String.valueOf(room3.room_id()))); + room1.room_id(), new TurnDto("GAMEOVER", room1.room_id()), + room2.room_id(), new TurnDto("WHITE", room2.room_id()), + room3.room_id(), new TurnDto("BLACK", room3.room_id())); @Test void 활성화된_모든_방을_불러온다() { diff --git a/src/test/java/repository/RoomDaoTest.java b/src/test/java/repository/RoomDaoTest.java index ca876a88847..b7845d8a25d 100644 --- a/src/test/java/repository/RoomDaoTest.java +++ b/src/test/java/repository/RoomDaoTest.java @@ -26,9 +26,9 @@ class RoomDaoTest { roomDao.add(new RoomDto(1)); roomDao.add(new RoomDto(2)); roomDao.add(new RoomDto(3)); - turnDao.add(new TurnDto("WHITE", "1")); - turnDao.add(new TurnDto("GAMEOVER", "2")); - turnDao.add(new TurnDto("BLACK", "3")); + turnDao.add(new TurnDto("WHITE", 1)); + turnDao.add(new TurnDto("GAMEOVER", 2)); + turnDao.add(new TurnDto("BLACK", 3)); List activeRoomAll = roomDao.findActiveRoomAll(); diff --git a/src/test/java/repository/TurnDaoTest.java b/src/test/java/repository/TurnDaoTest.java index 26c0eb58777..90cada99e79 100644 --- a/src/test/java/repository/TurnDaoTest.java +++ b/src/test/java/repository/TurnDaoTest.java @@ -1,6 +1,7 @@ package repository; import domain.piece.Color; +import dto.RoomDto; import dto.TurnDto; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; @@ -13,11 +14,12 @@ class TurnDaoTest { @Test void 턴을_저장한다() { - TurnDto whiteTurn = TurnDto.of(Color.WHITE); + TurnDto whiteTurn = new TurnDto("WHITE", 1); + RoomDto roomDto = new RoomDto(whiteTurn.gameId()); TurnDao turnDao = new TurnDao(); turnDao.update(whiteTurn); - assertThat(turnDao.findOne().getTurn()).isEqualTo(Color.WHITE); + assertThat(turnDao.findTurnByGameId(roomDto).getTurn()).isEqualTo(Color.WHITE); } } From 126fb313d44973818fd504281673d6cff97817a3 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sun, 31 Mar 2024 17:11:40 +0900 Subject: [PATCH 60/94] =?UTF-8?q?refactor:=20DAO=EC=97=90=20GameId=20?= =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/db/mysql/init/schema.sql | 4 ++-- src/main/java/repository/PieceDao.java | 21 ++++++++++++--------- src/main/java/repository/RoomDao.java | 14 ++++++++++---- src/main/java/repository/TurnDao.java | 21 ++++++++++++--------- 4 files changed, 36 insertions(+), 24 deletions(-) diff --git a/docker/db/mysql/init/schema.sql b/docker/db/mysql/init/schema.sql index 0fe2871cd09..db508a6f7bd 100644 --- a/docker/db/mysql/init/schema.sql +++ b/docker/db/mysql/init/schema.sql @@ -14,11 +14,11 @@ create table game_states create table pieces ( + game_id int, board_file varchar(1) not null, board_rank varchar(1) not null, color varchar(8) not null, type varchar(8) not null, - game_id int, - primary key (board_file, board_rank), + primary key (game_id, board_file, board_rank), foreign key (game_id) references rooms (room_id) ); diff --git a/src/main/java/repository/PieceDao.java b/src/main/java/repository/PieceDao.java index e7def73aada..338a838d4f4 100644 --- a/src/main/java/repository/PieceDao.java +++ b/src/main/java/repository/PieceDao.java @@ -3,6 +3,7 @@ import db.JdbcTemplate; import db.RowMapper; import dto.PieceDto; +import dto.RoomDto; import java.util.List; @@ -25,9 +26,11 @@ public class PieceDao { this.jdbcTemplate = jdbcTemplate; } - void add(final PieceDto piece) { - final String query = "INSERT INTO " + TABLE_NAME + " VALUES(?, ?, ?, ?)"; - jdbcTemplate.execute(query, piece.boardFile(), piece.boardRank(), piece.color(), piece.type()); + void add(final RoomDto room, final PieceDto piece) { + final String query = "INSERT INTO " + TABLE_NAME + " VALUES(?, ?, ?, ?, ?)"; + jdbcTemplate.execute(query, + String.valueOf(room.room_id()), piece.boardFile(), piece.boardRank(), + piece.color(), piece.type()); } PieceDto findOne(final String file, final String rank) { @@ -39,14 +42,14 @@ PieceDto findOne(final String file, final String rank) { return pieces.get(0); } - List findAll() { - final String query = "SELECT * FROM " + TABLE_NAME; - return jdbcTemplate.executeAndGet(query, rowMapper); + List findPieceByGameId(final int gameId) { + final String query = "SELECT * FROM " + TABLE_NAME + " WHERE game_id = ?"; + return jdbcTemplate.executeAndGet(query, rowMapper, String.valueOf(gameId)); } - void deleteAll() { - final String query = "DELETE FROM " + TABLE_NAME; - jdbcTemplate.execute(query); + void deleteAll(final RoomDto roomDto) { + final String query = "DELETE FROM " + TABLE_NAME + " WHERE game_id = ?"; + jdbcTemplate.execute(query, String.valueOf(roomDto.room_id())); } boolean hasRecords() { diff --git a/src/main/java/repository/RoomDao.java b/src/main/java/repository/RoomDao.java index 1fb6eb587fe..b48a6d40bf8 100644 --- a/src/main/java/repository/RoomDao.java +++ b/src/main/java/repository/RoomDao.java @@ -32,15 +32,21 @@ public void add(final RoomDto roomDto) { public Optional addNewRoom() { final String selectQuery = "SELECT MAX(room_id) AS room_id FROM " + TABLE_NAME; List roomDtos = jdbcTemplate.executeAndGet(selectQuery, rowMapper); + if (roomDtos.isEmpty()) { + final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (1)"; + int newRoomId = roomDtos.get(0).room_id() + 1; + jdbcTemplate.execute(insertQuery, String.valueOf(newRoomId)); + return Optional.of(new RoomDto(newRoomId)); + } final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (?)"; - final String roodId = String.valueOf(roomDtos.get(0).room_id() + 1); - jdbcTemplate.execute(insertQuery, roodId); - return Optional.ofNullable(roomDtos.get(0)); + int newRoomId = roomDtos.get(0).room_id() + 1; + jdbcTemplate.execute(insertQuery, String.valueOf(newRoomId)); + return Optional.of(new RoomDto(newRoomId)); } public Optional find(final String roomId) { final String query = "SELECT * FROM " + TABLE_NAME + " WHERE room_id = ?"; - List roomDtos = jdbcTemplate.executeAndGet(query, rowMapper, roomId); + final List roomDtos = jdbcTemplate.executeAndGet(query, rowMapper, roomId); return Optional.of(roomDtos.get(0)); } diff --git a/src/main/java/repository/TurnDao.java b/src/main/java/repository/TurnDao.java index 281bbd6ef66..858c084ad6f 100644 --- a/src/main/java/repository/TurnDao.java +++ b/src/main/java/repository/TurnDao.java @@ -26,7 +26,7 @@ public class TurnDao { void add(final TurnDto turnDto) { final String query = "INSERT INTO " + TABLE_NAME + " VALUES (?, ?)"; - jdbcTemplate.execute(query, turnDto.turn(), String.valueOf(turnDto.gameId())); + jdbcTemplate.execute(query, String.valueOf(turnDto.gameId()), turnDto.turn()); } TurnDto findTurnByGameId(final RoomDto roomDto) { @@ -38,15 +38,18 @@ TurnDto findTurnByGameId(final RoomDto roomDto) { return turns.get(0); } - void update(final TurnDto turnDto) { - final String deleteQuery = "DELETE FROM " + TABLE_NAME; - final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (?)"; - jdbcTemplate.execute(deleteQuery); - jdbcTemplate.execute(insertQuery, turnDto.turn()); + void update(final RoomDto roomDto, final TurnDto turnDto) { + final String insertQuery = "UPDATE " + TABLE_NAME + " SET state = ? WHERE game_id = ?"; + jdbcTemplate.execute(insertQuery, String.valueOf(roomDto.room_id()), turnDto.turn()); } - void deleteAll() { - final String query = "DELETE FROM " + TABLE_NAME; - jdbcTemplate.execute(query); + void delete(final RoomDto roomDto) { + final String query = "DELETE FROM " + TABLE_NAME + " WHERE game_id = ?"; + jdbcTemplate.execute(query, String.valueOf(roomDto.room_id())); + } + + void deleteAll(final RoomDto roomDto) { + final String query = "DELETE FROM " + TABLE_NAME + " WHERE game_id = ?"; + jdbcTemplate.execute(query, String.valueOf(roomDto.room_id())); } } From f69bc9b45e14afcbc5a1838f85c5ba2b121d2fc3 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sun, 31 Mar 2024 17:20:45 +0900 Subject: [PATCH 61/94] =?UTF-8?q?refactor:=20=EB=AA=85=EB=A0=B9=EC=96=B4?= =?UTF-8?q?=EB=A1=9C=20=EC=9E=85=EB=A0=A5=EB=90=9C=20position=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EB=A1=9C=EC=A7=81=EC=9D=84=20=EC=BB=A4=EB=A7=A8?= =?UTF-8?q?=EB=93=9C=20=EB=82=B4=EB=B6=80=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/command/MoveOnCommand.java | 13 +++++++++++++ src/main/java/view/command/CommandInput.java | 14 -------------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/main/java/controller/command/MoveOnCommand.java b/src/main/java/controller/command/MoveOnCommand.java index f2ec4655eeb..a6b57970473 100644 --- a/src/main/java/controller/command/MoveOnCommand.java +++ b/src/main/java/controller/command/MoveOnCommand.java @@ -6,8 +6,10 @@ import view.OutputView; import java.util.List; +import java.util.regex.Pattern; public class MoveOnCommand implements Command { + private static final Pattern POSITION_INPUT_PATTERN = Pattern.compile("^[A-H][1-8]$"); private static final int ARGUMENT_SIZE = 2; private final Position source; @@ -23,6 +25,17 @@ private void validateArgumentSize(final List arguments) { if (arguments.size() != ARGUMENT_SIZE) { throw new IllegalArgumentException(); } + validatePositions(arguments); + } + + private void validatePositions(final List inputs) { + inputs.forEach(this::validatePositionFormat); + } + + private void validatePositionFormat(final String positionInput) { + if (!POSITION_INPUT_PATTERN.matcher(positionInput).matches()) { + throw new IllegalArgumentException(); + } } @Override diff --git a/src/main/java/view/command/CommandInput.java b/src/main/java/view/command/CommandInput.java index f13db2253dd..ec3c22b8428 100644 --- a/src/main/java/view/command/CommandInput.java +++ b/src/main/java/view/command/CommandInput.java @@ -2,11 +2,8 @@ import java.util.List; import java.util.NoSuchElementException; -import java.util.regex.Pattern; public class CommandInput { - private static final Pattern POSITION_INPUT_PATTERN = Pattern.compile("^[a-h][1-8]$"); - private final List inputs; public CommandInput(final String input) { @@ -14,20 +11,9 @@ public CommandInput(final String input) { } private CommandInput(final List inputs) { - validatePositions(inputs.subList(1, inputs.size())); this.inputs = inputs; } - private void validatePositions(final List inputs) { - inputs.forEach(this::validatePositionFormat); - } - - private void validatePositionFormat(final String positionInput) { - if (!POSITION_INPUT_PATTERN.matcher(positionInput).matches()) { - throw new IllegalArgumentException(); - } - } - public String prefix() { if (inputs.isEmpty()) { throw new NoSuchElementException(); From 4c9b025d82c0500a38cc29517540ccf1e22daf9c Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sun, 31 Mar 2024 17:24:45 +0900 Subject: [PATCH 62/94] =?UTF-8?q?feat:=20=EA=B8=B0=EC=A1=B4=20=EA=B2=8C?= =?UTF-8?q?=EC=9E=84=EC=97=90=20=EB=B0=A9=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 14 +++-- ...ntroller.java => ChessGameController.java} | 25 ++++----- .../java/controller/GameRoomController.java | 53 +++++++++++++++++++ .../java/repository/ChessGameService.java | 21 +++----- src/main/java/view/InputView.java | 2 +- src/main/java/view/OutputView.java | 9 ++++ 6 files changed, 95 insertions(+), 29 deletions(-) rename src/main/java/controller/{ChessController.java => ChessGameController.java} (59%) create mode 100644 src/main/java/controller/GameRoomController.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index cc9df9d5376..dd71d07471a 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,9 +1,17 @@ -import controller.ChessController; +import controller.ChessGameController; +import controller.GameRoomController; +import dto.RoomDto; import repository.ChessGameService; +import repository.GameRoomService; public class Application { public static void main(String[] args) { - ChessController chessController = new ChessController(new ChessGameService()); - chessController.start(); + GameRoomController gameRoomController = new GameRoomController(new GameRoomService()); + ChessGameController chessGameController = new ChessGameController(new ChessGameService()); + + while (true) { + RoomDto roomDto = gameRoomController.run(); + chessGameController.start(roomDto); + } } } diff --git a/src/main/java/controller/ChessController.java b/src/main/java/controller/ChessGameController.java similarity index 59% rename from src/main/java/controller/ChessController.java rename to src/main/java/controller/ChessGameController.java index 9e9640744bb..961b0e024ab 100644 --- a/src/main/java/controller/ChessController.java +++ b/src/main/java/controller/ChessGameController.java @@ -3,32 +3,33 @@ import domain.ChessGame; import domain.board.ChessBoard; import domain.board.ChessBoardFactory; +import dto.RoomDto; import dto.TurnDto; import repository.ChessGameService; import view.InputView; import view.OutputView; -public class ChessController { +public class ChessGameController { private final ChessGameService chessGameService; private ChessGame chessGame; - public ChessController(final ChessGameService chessGameService) { + public ChessGameController(final ChessGameService chessGameService) { this.chessGameService = chessGameService; } - public void start() { - chessGame = new ChessGame(initializeChessGame()); + public void start(final RoomDto roomDto) { + chessGame = new ChessGame(initializeChessGame(roomDto)); OutputView.printGameGuideMessage(); while (chessGame.isPlaying()) { readCommandUntilValid(); } - updateGameStatus(); + updateGameStatus(roomDto); } - private ChessBoard initializeChessGame() { + private ChessBoard initializeChessGame(RoomDto roomDto) { try { - TurnDto turnDto = chessGameService.loadPreviousTurn(); - return ChessBoardFactory.loadPreviousChessBoard(chessGameService.loadPreviousData(), turnDto.getTurn()); + TurnDto turnDto = chessGameService.loadPreviousTurn(roomDto); + return ChessBoardFactory.loadPreviousChessBoard(chessGameService.loadPreviousData(roomDto), turnDto.getTurn()); } catch (IllegalArgumentException e) { return ChessBoardFactory.createInitialChessBoard(); } @@ -43,12 +44,12 @@ private void readCommandUntilValid() { } } - private void updateGameStatus() { + private void updateGameStatus(final RoomDto roomDto) { if (chessGame.isGameOver()) { - chessGameService.deletePreviousData(); + chessGameService.updateTurn(roomDto, new TurnDto("GAMEOVER", roomDto.room_id())); return; } - chessGameService.updatePiece(chessGame.getBoard().getPieces()); - chessGameService.updateTurn(TurnDto.of(chessGame.getTurn())); + chessGameService.updatePiece(roomDto, chessGame.getBoard().getPieces()); + chessGameService.updateTurn(roomDto, new TurnDto(chessGame.getTurn().name(), roomDto.room_id())); } } diff --git a/src/main/java/controller/GameRoomController.java b/src/main/java/controller/GameRoomController.java new file mode 100644 index 00000000000..1ceb075012c --- /dev/null +++ b/src/main/java/controller/GameRoomController.java @@ -0,0 +1,53 @@ +package controller; + +import dto.RoomDto; +import repository.GameRoomService; +import view.InputView; +import view.OutputView; +import view.command.CommandInput; + +import java.util.List; + +public class GameRoomController { + private final GameRoomService roomService; + + public GameRoomController(final GameRoomService roomService) { + this.roomService = roomService; + } + + public RoomDto run() { + List rooms = roomService.loadActiveRoomAll(); + if (rooms.isEmpty()) { + System.out.println("방이 존재하지 않습니다. 새로운 방을 생성해 주세요."); + } else { + System.out.println("입장할 방을 선택해 주세요."); + OutputView.printActiveRoomAll(rooms); + } + RoomDto roomDto = readCommandUntilValid(); + System.out.println(roomDto.room_id() + "번 방에 입장합니다."); + return roomDto; + } + + private RoomDto readCommandUntilValid() { + try { + return findRoom(); + } catch (IllegalArgumentException e) { + System.out.println(e.getMessage()); + return readCommandUntilValid(); + } + } + + private RoomDto findRoom() { + CommandInput commandInput = InputView.readCommandInput(); + + if (commandInput.prefix().equals("new")) { + return roomService.createNewRoom(); + } + if (commandInput.prefix().equals("room")) { + String roomId = commandInput.getArguments().get(0); + return roomService.findRoomById(roomId); + } + + throw new IllegalArgumentException("방을 찾을 수 없습니다."); + } +} diff --git a/src/main/java/repository/ChessGameService.java b/src/main/java/repository/ChessGameService.java index ba7f02d535f..af5ec162c58 100644 --- a/src/main/java/repository/ChessGameService.java +++ b/src/main/java/repository/ChessGameService.java @@ -26,28 +26,23 @@ public boolean isPreviousDataExist() { return pieceDao.hasRecords(); } - public List loadPreviousData() { - return pieceDao.findAll(); + public List loadPreviousData(final RoomDto roomDto) { + return pieceDao.findPieceByGameId(roomDto.room_id()); } public TurnDto loadPreviousTurn(final RoomDto roomDto) { return turnDao.findTurnByGameId(roomDto); } - public void updatePiece(final List pieceDtos) { - pieceDao.deleteAll(); + public void updatePiece(final RoomDto roomDto, final List pieceDtos) { + pieceDao.deleteAll(roomDto); for (PieceDto pieceDto : pieceDtos) { - pieceDao.add(pieceDto); + pieceDao.add(roomDto, pieceDto); } } - public void updateTurn(final TurnDto turnDto) { - turnDao.deleteAll(); - turnDao.update(turnDto); - } - - public void deletePreviousData() { - pieceDao.deleteAll(); - turnDao.deleteAll(); + public void updateTurn(final RoomDto roomDto, final TurnDto turnDto) { + turnDao.delete(roomDto); + turnDao.add(turnDto); } } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 0626dc6445c..7f1fdf0c26c 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -19,7 +19,7 @@ public static Command readCommand() { } } - private static CommandInput readCommandInput() { + public static CommandInput readCommandInput() { return new CommandInput(SCANNER.nextLine()); } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 54fb350bf89..aa0aaf9c703 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -2,6 +2,9 @@ import domain.board.ChessBoard; import domain.board.Score; +import dto.RoomDto; + +import java.util.List; public class OutputView { private static final MessageResolver messageResolver = new MessageResolver(); @@ -27,4 +30,10 @@ public static void printWinner(final Score score) { public static void printErrorMessage(Exception e) { System.out.println(e.getMessage()); } + + public static void printActiveRoomAll(final List rooms) { + for (RoomDto room : rooms) { + System.out.println("Room " + room.room_id()); + } + } } From c92d7198be8f3e218abd31eb6197c80cc2284626 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sun, 31 Mar 2024 17:26:10 +0900 Subject: [PATCH 63/94] =?UTF-8?q?chore:=20=EA=B8=B0=EB=B3=B4=20=EC=83=98?= =?UTF-8?q?=ED=94=8C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/sample.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/main/resources/sample.txt diff --git a/src/main/resources/sample.txt b/src/main/resources/sample.txt new file mode 100644 index 00000000000..5a4f6cc6093 --- /dev/null +++ b/src/main/resources/sample.txt @@ -0,0 +1,14 @@ +[BLACK 승리] +move f2 f3 +move e7 e5 +move g2 g4 +move d8 h4 +move h2 h3 +move h4 e1 + +[WHITE 승리] +move e2 e3 +move f7 f6 +move d1 h5 +move g8 h6 +move h5 e8 From d367afddcec8092b1cab527e7b970e61fc182862 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sun, 31 Mar 2024 22:28:13 +0900 Subject: [PATCH 64/94] =?UTF-8?q?refactor:=20DAO=20=EC=9D=B8=ED=84=B0?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EB=B6=84=EB=A6=AC,=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EB=AA=85=20=EC=88=98=EC=A0=95,=20service=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 4 +- .../java/controller/ChessGameController.java | 18 ++- .../java/controller/GameRoomController.java | 2 +- src/main/java/dto/StateDto.java | 10 ++ src/main/java/dto/TurnDto.java | 10 -- .../java/repository/ChessGameService.java | 48 ------ src/main/java/repository/GameStateDao.java | 13 ++ .../java/repository/GameStateDaoImpl.java | 42 +++++ src/main/java/repository/PieceDao.java | 54 +------ src/main/java/repository/PieceDaoImpl.java | 45 ++++++ src/main/java/repository/RoomDao.java | 52 +------ src/main/java/repository/RoomDaoImpl.java | 58 +++++++ src/main/java/repository/TurnDao.java | 55 ------- src/main/java/service/ChessGameService.java | 50 ++++++ .../GameRoomService.java | 6 +- .../java/repository/ChessGameServiceTest.java | 145 ------------------ .../java/repository/GameRoomServiceTest.java | 101 ------------ .../java/repository/GameStateMockDao.java | 23 +++ src/test/java/repository/PieceMockDao.java | 39 +++++ src/test/java/repository/RoomMockDao.java | 48 ++++++ .../java/service/ChessGameServiceTest.java | 83 ++++++++++ .../java/service/GameRoomServiceTest.java | 61 ++++++++ 22 files changed, 498 insertions(+), 469 deletions(-) create mode 100644 src/main/java/dto/StateDto.java delete mode 100644 src/main/java/dto/TurnDto.java delete mode 100644 src/main/java/repository/ChessGameService.java create mode 100644 src/main/java/repository/GameStateDao.java create mode 100644 src/main/java/repository/GameStateDaoImpl.java create mode 100644 src/main/java/repository/PieceDaoImpl.java create mode 100644 src/main/java/repository/RoomDaoImpl.java delete mode 100644 src/main/java/repository/TurnDao.java create mode 100644 src/main/java/service/ChessGameService.java rename src/main/java/{repository => service}/GameRoomService.java (85%) delete mode 100644 src/test/java/repository/ChessGameServiceTest.java delete mode 100644 src/test/java/repository/GameRoomServiceTest.java create mode 100644 src/test/java/repository/GameStateMockDao.java create mode 100644 src/test/java/repository/PieceMockDao.java create mode 100644 src/test/java/repository/RoomMockDao.java create mode 100644 src/test/java/service/ChessGameServiceTest.java create mode 100644 src/test/java/service/GameRoomServiceTest.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index dd71d07471a..b5b0786fbda 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,8 +1,8 @@ import controller.ChessGameController; import controller.GameRoomController; import dto.RoomDto; -import repository.ChessGameService; -import repository.GameRoomService; +import service.ChessGameService; +import service.GameRoomService; public class Application { public static void main(String[] args) { diff --git a/src/main/java/controller/ChessGameController.java b/src/main/java/controller/ChessGameController.java index 961b0e024ab..b7c50d8dfc7 100644 --- a/src/main/java/controller/ChessGameController.java +++ b/src/main/java/controller/ChessGameController.java @@ -4,11 +4,13 @@ import domain.board.ChessBoard; import domain.board.ChessBoardFactory; import dto.RoomDto; -import dto.TurnDto; -import repository.ChessGameService; +import dto.StateDto; +import service.ChessGameService; import view.InputView; import view.OutputView; +import java.util.NoSuchElementException; + public class ChessGameController { private final ChessGameService chessGameService; private ChessGame chessGame; @@ -28,9 +30,9 @@ public void start(final RoomDto roomDto) { private ChessBoard initializeChessGame(RoomDto roomDto) { try { - TurnDto turnDto = chessGameService.loadPreviousTurn(roomDto); - return ChessBoardFactory.loadPreviousChessBoard(chessGameService.loadPreviousData(roomDto), turnDto.getTurn()); - } catch (IllegalArgumentException e) { + StateDto stateDto = chessGameService.loadPreviousState(roomDto); + return ChessBoardFactory.loadPreviousChessBoard(chessGameService.loadPreviousPieces(roomDto), stateDto.getState()); + } catch (NoSuchElementException e) { return ChessBoardFactory.createInitialChessBoard(); } } @@ -46,10 +48,10 @@ private void readCommandUntilValid() { private void updateGameStatus(final RoomDto roomDto) { if (chessGame.isGameOver()) { - chessGameService.updateTurn(roomDto, new TurnDto("GAMEOVER", roomDto.room_id())); + chessGameService.updateState(new StateDto("GAMEOVER", roomDto.room_id())); return; } - chessGameService.updatePiece(roomDto, chessGame.getBoard().getPieces()); - chessGameService.updateTurn(roomDto, new TurnDto(chessGame.getTurn().name(), roomDto.room_id())); + chessGameService.updatePieces(roomDto, chessGame.getBoard().getPieces()); + chessGameService.updateState(new StateDto(chessGame.getTurn().name(), roomDto.room_id())); } } diff --git a/src/main/java/controller/GameRoomController.java b/src/main/java/controller/GameRoomController.java index 1ceb075012c..31e42b98ea4 100644 --- a/src/main/java/controller/GameRoomController.java +++ b/src/main/java/controller/GameRoomController.java @@ -1,7 +1,7 @@ package controller; import dto.RoomDto; -import repository.GameRoomService; +import service.GameRoomService; import view.InputView; import view.OutputView; import view.command.CommandInput; diff --git a/src/main/java/dto/StateDto.java b/src/main/java/dto/StateDto.java new file mode 100644 index 00000000000..4ad98c3e687 --- /dev/null +++ b/src/main/java/dto/StateDto.java @@ -0,0 +1,10 @@ +package dto; + + +import domain.piece.Color; + +public record StateDto(String state, int gameId) { + public Color getState() { + return Color.valueOf(state); + } +} diff --git a/src/main/java/dto/TurnDto.java b/src/main/java/dto/TurnDto.java deleted file mode 100644 index ff5581f968b..00000000000 --- a/src/main/java/dto/TurnDto.java +++ /dev/null @@ -1,10 +0,0 @@ -package dto; - - -import domain.piece.Color; - -public record TurnDto(String turn, int gameId) { - public Color getTurn() { - return Color.valueOf(turn); - } -} diff --git a/src/main/java/repository/ChessGameService.java b/src/main/java/repository/ChessGameService.java deleted file mode 100644 index af5ec162c58..00000000000 --- a/src/main/java/repository/ChessGameService.java +++ /dev/null @@ -1,48 +0,0 @@ -package repository; - -import db.JdbcTemplate; -import dto.PieceDto; -import dto.RoomDto; -import dto.TurnDto; - -import java.util.List; - -public class ChessGameService { - private final PieceDao pieceDao; - private final TurnDao turnDao; - - ChessGameService(final PieceDao pieceDao, final TurnDao turnDao) { - this.pieceDao = pieceDao; - this.turnDao = turnDao; - } - - public ChessGameService() { - final JdbcTemplate jdbcTemplate = new JdbcTemplate(); - this.pieceDao = new PieceDao(jdbcTemplate); - this.turnDao = new TurnDao(jdbcTemplate); - } - - public boolean isPreviousDataExist() { - return pieceDao.hasRecords(); - } - - public List loadPreviousData(final RoomDto roomDto) { - return pieceDao.findPieceByGameId(roomDto.room_id()); - } - - public TurnDto loadPreviousTurn(final RoomDto roomDto) { - return turnDao.findTurnByGameId(roomDto); - } - - public void updatePiece(final RoomDto roomDto, final List pieceDtos) { - pieceDao.deleteAll(roomDto); - for (PieceDto pieceDto : pieceDtos) { - pieceDao.add(roomDto, pieceDto); - } - } - - public void updateTurn(final RoomDto roomDto, final TurnDto turnDto) { - turnDao.delete(roomDto); - turnDao.add(turnDto); - } -} diff --git a/src/main/java/repository/GameStateDao.java b/src/main/java/repository/GameStateDao.java new file mode 100644 index 00000000000..91fed24e66d --- /dev/null +++ b/src/main/java/repository/GameStateDao.java @@ -0,0 +1,13 @@ +package repository; + +import dto.StateDto; + +import java.util.Optional; + +public interface GameStateDao { + void add(StateDto stateDto); + + Optional findByGameId(int gameId); + + void deleteByGameId(int gameId); +} diff --git a/src/main/java/repository/GameStateDaoImpl.java b/src/main/java/repository/GameStateDaoImpl.java new file mode 100644 index 00000000000..a21c3c19355 --- /dev/null +++ b/src/main/java/repository/GameStateDaoImpl.java @@ -0,0 +1,42 @@ +package repository; + +import db.JdbcTemplate; +import db.RowMapper; +import dto.StateDto; + +import java.util.List; +import java.util.Optional; + +public class GameStateDaoImpl implements GameStateDao { + private static final String TABLE_NAME = "game_states"; + + private final JdbcTemplate jdbcTemplate; + private final RowMapper rowMapper = (resultSet) -> new StateDto( + resultSet.getString("state"), + resultSet.getInt("game_id") + ); + + GameStateDaoImpl() { + this(new JdbcTemplate()); + } + + public GameStateDaoImpl(final JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + public void add(final StateDto stateDto) { + final String query = "INSERT INTO " + TABLE_NAME + " VALUES (?, ?)"; + jdbcTemplate.execute(query, String.valueOf(stateDto.gameId()), stateDto.state()); + } + + public Optional findByGameId(final int gameId) { + final String query = "SELECT * FROM " + TABLE_NAME + " WHERE game_id = ? LIMIT 1"; + final List turns = jdbcTemplate.executeAndGet(query, rowMapper, String.valueOf(gameId)); + return Optional.ofNullable(turns.get(0)); + } + + public void deleteByGameId(final int gameId) { + final String query = "DELETE FROM " + TABLE_NAME + " WHERE game_id = ?"; + jdbcTemplate.execute(query, String.valueOf(gameId)); + } +} diff --git a/src/main/java/repository/PieceDao.java b/src/main/java/repository/PieceDao.java index 338a838d4f4..a72264bee8a 100644 --- a/src/main/java/repository/PieceDao.java +++ b/src/main/java/repository/PieceDao.java @@ -1,60 +1,14 @@ package repository; -import db.JdbcTemplate; -import db.RowMapper; import dto.PieceDto; import dto.RoomDto; import java.util.List; -public class PieceDao { - private static final String TABLE_NAME = "pieces"; +public interface PieceDao { + void add(RoomDto room, PieceDto piece); - private final JdbcTemplate jdbcTemplate; - private final RowMapper rowMapper = (resultSet) -> new PieceDto( - resultSet.getString("board_file"), - resultSet.getString("board_rank"), - resultSet.getString("color"), - resultSet.getString("type") - ); + List findPieceByGameId(int gameId); - PieceDao() { - this(new JdbcTemplate()); - } - - PieceDao(final JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - void add(final RoomDto room, final PieceDto piece) { - final String query = "INSERT INTO " + TABLE_NAME + " VALUES(?, ?, ?, ?, ?)"; - jdbcTemplate.execute(query, - String.valueOf(room.room_id()), piece.boardFile(), piece.boardRank(), - piece.color(), piece.type()); - } - - PieceDto findOne(final String file, final String rank) { - final String query = "SELECT * FROM " + TABLE_NAME + " WHERE board_file = ? and board_rank = ? limit 1"; - final List pieces = jdbcTemplate.executeAndGet(query, rowMapper, file, rank); - if (pieces.isEmpty()) { - throw new IllegalArgumentException("데이터가 없습니다."); - } - return pieces.get(0); - } - - List findPieceByGameId(final int gameId) { - final String query = "SELECT * FROM " + TABLE_NAME + " WHERE game_id = ?"; - return jdbcTemplate.executeAndGet(query, rowMapper, String.valueOf(gameId)); - } - - void deleteAll(final RoomDto roomDto) { - final String query = "DELETE FROM " + TABLE_NAME + " WHERE game_id = ?"; - jdbcTemplate.execute(query, String.valueOf(roomDto.room_id())); - } - - boolean hasRecords() { - final String query = "SELECT * FROM " + TABLE_NAME + " LIMIT 1"; - final List pieces = jdbcTemplate.executeAndGet(query, rowMapper); - return !pieces.isEmpty(); - } + void deleteAllByGameId(int gameId); } diff --git a/src/main/java/repository/PieceDaoImpl.java b/src/main/java/repository/PieceDaoImpl.java new file mode 100644 index 00000000000..4d9a7df9f80 --- /dev/null +++ b/src/main/java/repository/PieceDaoImpl.java @@ -0,0 +1,45 @@ +package repository; + +import db.JdbcTemplate; +import db.RowMapper; +import dto.PieceDto; +import dto.RoomDto; + +import java.util.List; + +public class PieceDaoImpl implements PieceDao { + private static final String TABLE_NAME = "pieces"; + + private final JdbcTemplate jdbcTemplate; + private final RowMapper rowMapper = (resultSet) -> new PieceDto( + resultSet.getString("board_file"), + resultSet.getString("board_rank"), + resultSet.getString("color"), + resultSet.getString("type") + ); + + PieceDaoImpl() { + this(new JdbcTemplate()); + } + + public PieceDaoImpl(final JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + public void add(final RoomDto room, final PieceDto piece) { + final String query = "INSERT INTO " + TABLE_NAME + " VALUES(?, ?, ?, ?, ?)"; + jdbcTemplate.execute(query, + String.valueOf(room.room_id()), piece.boardFile(), piece.boardRank(), + piece.color(), piece.type()); + } + + public List findPieceByGameId(final int gameId) { + final String query = "SELECT * FROM " + TABLE_NAME + " WHERE game_id = ?"; + return jdbcTemplate.executeAndGet(query, rowMapper, String.valueOf(gameId)); + } + + public void deleteAllByGameId(final int gameId) { + final String query = "DELETE FROM " + TABLE_NAME + " WHERE game_id = ?"; + jdbcTemplate.execute(query, String.valueOf(gameId)); + } +} diff --git a/src/main/java/repository/RoomDao.java b/src/main/java/repository/RoomDao.java index b48a6d40bf8..345fec26e6d 100644 --- a/src/main/java/repository/RoomDao.java +++ b/src/main/java/repository/RoomDao.java @@ -1,58 +1,16 @@ package repository; -import db.JdbcTemplate; -import db.RowMapper; import dto.RoomDto; import java.util.List; import java.util.Optional; -public class RoomDao { - private static final String TABLE_NAME = "rooms"; - private static final String GAME_STATUES_TABLE_NAME = "game_states"; +public interface RoomDao { + void add(RoomDto roomDto); - private final JdbcTemplate jdbcTemplate; - private final RowMapper rowMapper = (resultSet) -> new RoomDto( - resultSet.getInt("room_id") - ); + Optional addNewRoom(); - RoomDao() { - this(new JdbcTemplate()); - } + Optional find(String roomId); - RoomDao(final JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - public void add(final RoomDto roomDto) { - final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (?)"; - jdbcTemplate.execute(insertQuery, "" + roomDto.room_id()); - } - - public Optional addNewRoom() { - final String selectQuery = "SELECT MAX(room_id) AS room_id FROM " + TABLE_NAME; - List roomDtos = jdbcTemplate.executeAndGet(selectQuery, rowMapper); - if (roomDtos.isEmpty()) { - final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (1)"; - int newRoomId = roomDtos.get(0).room_id() + 1; - jdbcTemplate.execute(insertQuery, String.valueOf(newRoomId)); - return Optional.of(new RoomDto(newRoomId)); - } - final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (?)"; - int newRoomId = roomDtos.get(0).room_id() + 1; - jdbcTemplate.execute(insertQuery, String.valueOf(newRoomId)); - return Optional.of(new RoomDto(newRoomId)); - } - - public Optional find(final String roomId) { - final String query = "SELECT * FROM " + TABLE_NAME + " WHERE room_id = ?"; - final List roomDtos = jdbcTemplate.executeAndGet(query, rowMapper, roomId); - return Optional.of(roomDtos.get(0)); - } - - public List findActiveRoomAll() { - final String query = "SELECT * FROM " + TABLE_NAME + " AS r JOIN " - + GAME_STATUES_TABLE_NAME + " AS s ON r.room_id = s.game_id WHERE s.state != 'GAMEOVER'"; - return jdbcTemplate.executeAndGet(query, rowMapper); - } + List findActiveRoomAll(); } diff --git a/src/main/java/repository/RoomDaoImpl.java b/src/main/java/repository/RoomDaoImpl.java new file mode 100644 index 00000000000..1da3b5accdf --- /dev/null +++ b/src/main/java/repository/RoomDaoImpl.java @@ -0,0 +1,58 @@ +package repository; + +import db.JdbcTemplate; +import db.RowMapper; +import dto.RoomDto; + +import java.util.List; +import java.util.Optional; + +public class RoomDaoImpl implements RoomDao { + private static final String TABLE_NAME = "rooms"; + private static final String GAME_STATUES_TABLE_NAME = "game_states"; + + private final JdbcTemplate jdbcTemplate; + private final RowMapper rowMapper = (resultSet) -> new RoomDto( + resultSet.getInt("room_id") + ); + + RoomDaoImpl() { + this(new JdbcTemplate()); + } + + public RoomDaoImpl(final JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + public void add(final RoomDto roomDto) { + final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (?)"; + jdbcTemplate.execute(insertQuery, "" + roomDto.room_id()); + } + + public Optional addNewRoom() { + final String selectQuery = "SELECT MAX(room_id) AS room_id FROM " + TABLE_NAME; + List roomDtos = jdbcTemplate.executeAndGet(selectQuery, rowMapper); + if (roomDtos.isEmpty()) { + final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (1)"; + int newRoomId = roomDtos.get(0).room_id() + 1; + jdbcTemplate.execute(insertQuery, String.valueOf(newRoomId)); + return Optional.of(new RoomDto(newRoomId)); + } + final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (?)"; + int newRoomId = roomDtos.get(0).room_id() + 1; + jdbcTemplate.execute(insertQuery, String.valueOf(newRoomId)); + return Optional.of(new RoomDto(newRoomId)); + } + + public Optional find(final String roomId) { + final String query = "SELECT * FROM " + TABLE_NAME + " WHERE room_id = ?"; + final List roomDtos = jdbcTemplate.executeAndGet(query, rowMapper, roomId); + return Optional.of(roomDtos.get(0)); + } + + public List findActiveRoomAll() { + final String query = "SELECT * FROM " + TABLE_NAME + " AS r JOIN " + + GAME_STATUES_TABLE_NAME + " AS s ON r.room_id = s.game_id WHERE s.state != 'GAMEOVER'"; + return jdbcTemplate.executeAndGet(query, rowMapper); + } +} diff --git a/src/main/java/repository/TurnDao.java b/src/main/java/repository/TurnDao.java deleted file mode 100644 index 858c084ad6f..00000000000 --- a/src/main/java/repository/TurnDao.java +++ /dev/null @@ -1,55 +0,0 @@ -package repository; - -import db.JdbcTemplate; -import db.RowMapper; -import dto.RoomDto; -import dto.TurnDto; - -import java.util.List; - -public class TurnDao { - private static final String TABLE_NAME = "game_states"; - - private final JdbcTemplate jdbcTemplate; - private final RowMapper rowMapper = (resultSet) -> new TurnDto( - resultSet.getString("state"), - resultSet.getInt("game_id") - ); - - TurnDao() { - this(new JdbcTemplate()); - } - - TurnDao(final JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - void add(final TurnDto turnDto) { - final String query = "INSERT INTO " + TABLE_NAME + " VALUES (?, ?)"; - jdbcTemplate.execute(query, String.valueOf(turnDto.gameId()), turnDto.turn()); - } - - TurnDto findTurnByGameId(final RoomDto roomDto) { - final String query = "SELECT * FROM " + TABLE_NAME + " WHERE game_id = ?"; - final List turns = jdbcTemplate.executeAndGet(query, rowMapper, String.valueOf(roomDto.room_id())); - if (turns.isEmpty()) { - throw new IllegalArgumentException("데이터가 없습니다."); - } - return turns.get(0); - } - - void update(final RoomDto roomDto, final TurnDto turnDto) { - final String insertQuery = "UPDATE " + TABLE_NAME + " SET state = ? WHERE game_id = ?"; - jdbcTemplate.execute(insertQuery, String.valueOf(roomDto.room_id()), turnDto.turn()); - } - - void delete(final RoomDto roomDto) { - final String query = "DELETE FROM " + TABLE_NAME + " WHERE game_id = ?"; - jdbcTemplate.execute(query, String.valueOf(roomDto.room_id())); - } - - void deleteAll(final RoomDto roomDto) { - final String query = "DELETE FROM " + TABLE_NAME + " WHERE game_id = ?"; - jdbcTemplate.execute(query, String.valueOf(roomDto.room_id())); - } -} diff --git a/src/main/java/service/ChessGameService.java b/src/main/java/service/ChessGameService.java new file mode 100644 index 00000000000..85cd84a4c44 --- /dev/null +++ b/src/main/java/service/ChessGameService.java @@ -0,0 +1,50 @@ +package service; + +import db.JdbcTemplate; +import dto.PieceDto; +import dto.RoomDto; +import dto.StateDto; +import repository.GameStateDao; +import repository.PieceDao; +import repository.PieceDaoImpl; +import repository.GameStateDaoImpl; + +import java.util.List; +import java.util.NoSuchElementException; + +public class ChessGameService { + private final PieceDao pieceDao; + private final GameStateDao gameStateDao; + + ChessGameService(final PieceDao pieceDao, final GameStateDao gameStateDao) { + this.pieceDao = pieceDao; + this.gameStateDao = gameStateDao; + } + + public ChessGameService() { + final JdbcTemplate jdbcTemplate = new JdbcTemplate(); + this.pieceDao = new PieceDaoImpl(jdbcTemplate); + this.gameStateDao = new GameStateDaoImpl(jdbcTemplate); + } + + public List loadPreviousPieces(final RoomDto roomDto) { + return pieceDao.findPieceByGameId(roomDto.room_id()); + } + + public StateDto loadPreviousState(final RoomDto roomDto) { + return gameStateDao.findByGameId(roomDto.room_id()) + .orElseThrow(NoSuchElementException::new); + } + + public void updatePieces(final RoomDto roomDto, final List pieceDtos) { + pieceDao.deleteAllByGameId(roomDto.room_id()); + for (PieceDto pieceDto : pieceDtos) { + pieceDao.add(roomDto, pieceDto); + } + } + + public void updateState(final StateDto stateDto) { + gameStateDao.deleteByGameId(stateDto.gameId()); + gameStateDao.add(stateDto); + } +} diff --git a/src/main/java/repository/GameRoomService.java b/src/main/java/service/GameRoomService.java similarity index 85% rename from src/main/java/repository/GameRoomService.java rename to src/main/java/service/GameRoomService.java index 72650ec71a4..bbf1daf9d73 100644 --- a/src/main/java/repository/GameRoomService.java +++ b/src/main/java/service/GameRoomService.java @@ -1,7 +1,9 @@ -package repository; +package service; import db.JdbcTemplate; import dto.RoomDto; +import repository.RoomDao; +import repository.RoomDaoImpl; import java.util.List; import java.util.Optional; @@ -15,7 +17,7 @@ public class GameRoomService { public GameRoomService() { final JdbcTemplate jdbcTemplate = new JdbcTemplate(); - this.roomDao = new RoomDao(jdbcTemplate); + this.roomDao = new RoomDaoImpl(jdbcTemplate); } public List loadActiveRoomAll() { diff --git a/src/test/java/repository/ChessGameServiceTest.java b/src/test/java/repository/ChessGameServiceTest.java deleted file mode 100644 index 5327d6f06d8..00000000000 --- a/src/test/java/repository/ChessGameServiceTest.java +++ /dev/null @@ -1,145 +0,0 @@ -package repository; - -import domain.piece.Color; -import domain.position.Position; -import dto.PieceDto; -import dto.RoomDto; -import dto.TurnDto; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator; -import org.junit.jupiter.api.Test; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; - -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -@SuppressWarnings("NonAsciiCharacters") -class ChessGameServiceTest { - private static final PieceDto A2WhitePawn = new PieceDto("A", "2", "WHITE", "PAWN"); - private static final PieceDto B2WhitePawn = new PieceDto("B", "2", "WHITE", "PAWN"); - private static final PieceDto C2WhitePawn = new PieceDto("C", "2", "WHITE", "PAWN"); - private static final TurnDto whiteTurn = new TurnDto("WHITE", 1); - private static final TurnDto blackTurn = new TurnDto("BLACK", 2); - - private final PieceDao pieceDao = new PieceMockDao(); - private final TurnDao turnDao = new TurnMockDao(); - private final ChessGameService chessGameService = new ChessGameService(pieceDao, turnDao); - - @BeforeEach - void setData() { - pieceDao.add(A2WhitePawn); - pieceDao.add(B2WhitePawn); - pieceDao.add(C2WhitePawn); - turnDao.update(whiteTurn); - } - - @AfterEach - void rollback() { - pieceDao.deleteAll(); - turnDao.deleteAll(); - } - - @Test - void 이전_게임_데이터가_존재한다() { - assertThat(chessGameService.isPreviousDataExist()).isTrue(); - } - - @Test - void 이전_게임_데이터를_불러온다() { - assertThat(chessGameService.loadPreviousData()) - .containsExactlyInAnyOrder(A2WhitePawn, B2WhitePawn, C2WhitePawn); - } - - @Test - void 이전_게임의_턴_데이터를_불러온다() { - RoomDto roomDto = new RoomDto(1); - - assertThat(chessGameService.loadPreviousTurn(roomDto).getTurn()) - .isEqualTo(Color.WHITE); - } - - @Test - void 피스_데이터를_갱신한다() { - PieceDto A3WhitePawn = new PieceDto("A", "3", "WHITE", "PAWN"); - PieceDto B3WhitePawn = new PieceDto("B", "3", "WHITE", "PAWN"); - PieceDto C3WhitePawn = new PieceDto("C", "3", "WHITE", "PAWN"); - - List pieceDtos = List.of(A3WhitePawn, B3WhitePawn, C3WhitePawn); - - chessGameService.updatePiece(pieceDtos); - - assertThat(chessGameService.loadPreviousData()) - .containsExactlyInAnyOrder(A3WhitePawn, B3WhitePawn, C3WhitePawn); - } - - @Test - void 턴_데이터를_갱신한다() { - RoomDto room = new RoomDto(blackTurn.gameId()); - - chessGameService.updateTurn(blackTurn); - - assertThat(chessGameService.loadPreviousTurn(room).getTurn()) - .isEqualTo(Color.BLACK); - } - - @Test - void 모든_데이터를_삭제한다() { - chessGameService.deletePreviousData(); - - assertThat(chessGameService.isPreviousDataExist()).isFalse(); - } - - static class PieceMockDao extends PieceDao { - private Map repository = new HashMap<>(); - - void add(final PieceDto piece) { - Position position = new Position(piece.boardFile() + piece.boardRank()); - repository.put(position, piece); - } - - PieceDto findOne(final String file, final String rank) { - Position position = new Position(file + rank); - if (!repository.containsKey(position)) { - throw new IllegalArgumentException("데이터가 없습니다."); - } - return repository.get(position); - } - - List findAll() { - return repository.values().stream().toList(); - } - - void deleteAll() { - repository = new HashMap<>(); - } - - boolean hasRecords() { - return repository.keySet().size() != 0; - } - } - - - static class TurnMockDao extends TurnDao { - private final Map repository = new HashMap<>(); - - void add(TurnDto turnDto) { - repository.put(turnDto.gameId(), turnDto); - } - - TurnDto findTurnByGameId(RoomDto roomDto) { - if (!repository.containsKey(roomDto.room_id())) { - throw new IllegalArgumentException("데이터가 없습니다."); - } - return repository.get(roomDto.room_id()); - } - - void update(final TurnDto turnDto) { - repository.put(turnDto.gameId(), turnDto); - } - } -} diff --git a/src/test/java/repository/GameRoomServiceTest.java b/src/test/java/repository/GameRoomServiceTest.java deleted file mode 100644 index ae46bef2bda..00000000000 --- a/src/test/java/repository/GameRoomServiceTest.java +++ /dev/null @@ -1,101 +0,0 @@ -package repository; - -import dto.RoomDto; -import dto.TurnDto; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator; -import org.junit.jupiter.api.Test; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; - -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -@SuppressWarnings("NonAsciiCharacters") -class GameRoomServiceTest { - private final RoomDto room1 = new RoomDto(1); - private final RoomDto room2 = new RoomDto(2); - private final RoomDto room3 = new RoomDto(3); - - private final Map roomRepository = Map.of( - room1.room_id(), room1, - room2.room_id(), room2, - room3.room_id(), room3); - - private final Map turnRepository = Map.of( - room1.room_id(), new TurnDto("GAMEOVER", room1.room_id()), - room2.room_id(), new TurnDto("WHITE", room2.room_id()), - room3.room_id(), new TurnDto("BLACK", room3.room_id())); - - @Test - void 활성화된_모든_방을_불러온다() { - RoomDao roomDao = new RoomMockDao(roomRepository, turnRepository); - GameRoomService gameRoomService = new GameRoomService(roomDao); - - assertThat(gameRoomService.loadActiveRoomAll()) - .containsExactlyInAnyOrder(room2, room3); - } - - @Test - void ID로_방을_찾는다() { - RoomDao roomDao = new RoomMockDao(roomRepository, turnRepository); - GameRoomService gameRoomService = new GameRoomService(roomDao); - - RoomDto findRoom = gameRoomService.findRoomById("1"); - - assertThat(findRoom).isEqualTo(room1); - } - - @Test - void 새로운_방을_만든다() { - RoomDao roomDao = new RoomMockDao(new HashMap<>(), new HashMap<>()); - GameRoomService gameRoomService = new GameRoomService(roomDao); - - assertThatCode(gameRoomService::createNewRoom) - .doesNotThrowAnyException(); - } - - static class RoomMockDao extends RoomDao { - private final Map roomRepository; - private final Map turnRepository; - - public RoomMockDao(Map roomRepository, Map turnRepository) { - this.roomRepository = roomRepository; - this.turnRepository = turnRepository; - } - - public void add(final RoomDto roomDto) { - roomRepository.put(roomDto.room_id(), roomDto); - } - - public Optional addNewRoom() { - if (roomRepository.keySet().isEmpty()) { - RoomDto newRoomDto = new RoomDto(1); - roomRepository.put(newRoomDto.room_id(), newRoomDto); - return Optional.of(newRoomDto); - } - - int newRoomId = Collections.max(roomRepository.keySet()) + 1; - RoomDto newRoomDto = new RoomDto(newRoomId); - roomRepository.put(newRoomDto.room_id(), newRoomDto); - return Optional.of(newRoomDto); - } - - public Optional find(final String roomId) { - return Optional.of(roomRepository.get(Integer.parseInt(roomId))); - } - - public List findActiveRoomAll() { - return roomRepository.keySet().stream() - .filter(roomId -> !Objects.equals(turnRepository.get(roomId).turn(), "GAMEOVER")) - .map(roomRepository::get) - .toList(); - } - } -} diff --git a/src/test/java/repository/GameStateMockDao.java b/src/test/java/repository/GameStateMockDao.java new file mode 100644 index 00000000000..919ecb84df6 --- /dev/null +++ b/src/test/java/repository/GameStateMockDao.java @@ -0,0 +1,23 @@ +package repository; + +import dto.StateDto; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public class GameStateMockDao implements GameStateDao { + private final Map repository = new HashMap<>(); + + public void add(StateDto stateDto) { + repository.put(stateDto.gameId(), stateDto); + } + + public Optional findByGameId(final int gameId) { + return Optional.ofNullable(repository.get(gameId)); + } + + public void deleteByGameId(final int gameId) { + repository.remove(gameId); + } +} diff --git a/src/test/java/repository/PieceMockDao.java b/src/test/java/repository/PieceMockDao.java new file mode 100644 index 00000000000..5f3eeb9998e --- /dev/null +++ b/src/test/java/repository/PieceMockDao.java @@ -0,0 +1,39 @@ +package repository; + +import dto.PieceDto; +import dto.RoomDto; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class PieceMockDao implements PieceDao { + private Map repository = new HashMap<>(); + + public void add(final RoomDto room, final PieceDto piece) { + String key = generateKey(room, piece); + repository.put(key, piece); + } + + public List findPieceByGameId(final int gameId) { + return repository.entrySet().stream() + .filter(entry -> extractGameIdFromKey(entry.getKey()) == gameId) + .map(Map.Entry::getValue) + .toList(); + } + + public void deleteAllByGameId(final int gameId) { + repository = repository.entrySet().stream() + .filter(entry -> extractGameIdFromKey(entry.getKey()) != gameId) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + + private String generateKey(RoomDto room, PieceDto piece) { + return room.room_id() + "-" + piece.boardFile() + "-" + piece.boardRank(); + } + + private int extractGameIdFromKey(String key) { + return Integer.parseInt(key.split("-")[0]); + } +} diff --git a/src/test/java/repository/RoomMockDao.java b/src/test/java/repository/RoomMockDao.java new file mode 100644 index 00000000000..e1a801945c4 --- /dev/null +++ b/src/test/java/repository/RoomMockDao.java @@ -0,0 +1,48 @@ +package repository; + +import dto.RoomDto; +import dto.StateDto; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +public class RoomMockDao implements RoomDao { + private final Map roomRepository; + private final Map turnRepository; + + public RoomMockDao(Map roomRepository, Map turnRepository) { + this.roomRepository = roomRepository; + this.turnRepository = turnRepository; + } + + public void add(final RoomDto roomDto) { + roomRepository.put(roomDto.room_id(), roomDto); + } + + public Optional addNewRoom() { + if (roomRepository.keySet().isEmpty()) { + RoomDto newRoomDto = new RoomDto(1); + roomRepository.put(newRoomDto.room_id(), newRoomDto); + return Optional.of(newRoomDto); + } + + int newRoomId = Collections.max(roomRepository.keySet()) + 1; + RoomDto newRoomDto = new RoomDto(newRoomId); + roomRepository.put(newRoomDto.room_id(), newRoomDto); + return Optional.of(newRoomDto); + } + + public Optional find(final String roomId) { + return Optional.of(roomRepository.get(Integer.parseInt(roomId))); + } + + public List findActiveRoomAll() { + return roomRepository.keySet().stream() + .filter(roomId -> !Objects.equals(turnRepository.get(roomId).state(), "GAMEOVER")) + .map(roomRepository::get) + .toList(); + } +} diff --git a/src/test/java/service/ChessGameServiceTest.java b/src/test/java/service/ChessGameServiceTest.java new file mode 100644 index 00000000000..b96278ddf80 --- /dev/null +++ b/src/test/java/service/ChessGameServiceTest.java @@ -0,0 +1,83 @@ +package service; + +import domain.piece.Color; +import dto.PieceDto; +import dto.RoomDto; +import dto.StateDto; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; +import repository.GameStateDao; +import repository.GameStateMockDao; +import repository.PieceDao; +import repository.PieceMockDao; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") +class ChessGameServiceTest { + private static final PieceDto A2WhitePawn = new PieceDto("A", "2", "WHITE", "PAWN"); + private static final PieceDto B2WhitePawn = new PieceDto("B", "2", "WHITE", "PAWN"); + private static final PieceDto C2WhitePawn = new PieceDto("C", "2", "WHITE", "PAWN"); + private static final StateDto whiteTurn = new StateDto("WHITE", 1); + private static final StateDto blackTurn = new StateDto("BLACK", 2); + private static final RoomDto room1 = new RoomDto(1); + + private final PieceDao pieceDao = new PieceMockDao(); + private final GameStateDao gameStateDao = new GameStateMockDao(); + private final ChessGameService chessGameService = new ChessGameService(pieceDao, gameStateDao); + + @BeforeEach + void setData() { + pieceDao.add(room1, A2WhitePawn); + pieceDao.add(room1, B2WhitePawn); + pieceDao.add(room1, C2WhitePawn); + gameStateDao.add(whiteTurn); + } + + @AfterEach + void rollback() { + pieceDao.deleteAllByGameId(1); + gameStateDao.deleteByGameId(1); + } + + @Test + void 이전_게임의_피스_데이터를_불러온다() { + assertThat(chessGameService.loadPreviousPieces(room1)) + .containsExactlyInAnyOrder(A2WhitePawn, B2WhitePawn, C2WhitePawn); + } + + @Test + void 이전_게임의_턴_데이터를_불러온다() { + assertThat(chessGameService.loadPreviousState(room1).getState()) + .isEqualTo(Color.WHITE); + } + + @Test + void 피스_데이터를_갱신한다() { + RoomDto roomDto = room1; + PieceDto A3WhitePawn = new PieceDto("A", "3", "WHITE", "PAWN"); + PieceDto B3WhitePawn = new PieceDto("B", "3", "WHITE", "PAWN"); + PieceDto C3WhitePawn = new PieceDto("C", "3", "WHITE", "PAWN"); + + chessGameService.updatePieces(roomDto, List.of(A3WhitePawn, B3WhitePawn, C3WhitePawn)); + + assertThat(chessGameService.loadPreviousPieces(roomDto)) + .containsExactlyInAnyOrder(A3WhitePawn, B3WhitePawn, C3WhitePawn); + } + + @Test + void 턴_데이터를_갱신한다() { + RoomDto room = new RoomDto(blackTurn.gameId()); + + chessGameService.updateState(blackTurn); + + assertThat(chessGameService.loadPreviousState(room).getState()) + .isEqualTo(Color.BLACK); + } +} diff --git a/src/test/java/service/GameRoomServiceTest.java b/src/test/java/service/GameRoomServiceTest.java new file mode 100644 index 00000000000..9accd0111ed --- /dev/null +++ b/src/test/java/service/GameRoomServiceTest.java @@ -0,0 +1,61 @@ +package service; + +import dto.RoomDto; +import dto.StateDto; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; +import repository.RoomDao; +import repository.RoomMockDao; + +import java.util.HashMap; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") +class GameRoomServiceTest { + private final RoomDto room1 = new RoomDto(1); + private final RoomDto room2 = new RoomDto(2); + private final RoomDto room3 = new RoomDto(3); + + private final Map roomRepository = Map.of( + room1.room_id(), room1, + room2.room_id(), room2, + room3.room_id(), room3); + + private final Map turnRepository = Map.of( + room1.room_id(), new StateDto("GAMEOVER", room1.room_id()), + room2.room_id(), new StateDto("WHITE", room2.room_id()), + room3.room_id(), new StateDto("BLACK", room3.room_id())); + + @Test + void 활성화된_모든_방을_불러온다() { + RoomDao roomDao = new RoomMockDao(roomRepository, turnRepository); + GameRoomService gameRoomService = new GameRoomService(roomDao); + + assertThat(gameRoomService.loadActiveRoomAll()) + .containsExactlyInAnyOrder(room2, room3); + } + + @Test + void ID로_방을_찾는다() { + RoomDao roomDao = new RoomMockDao(roomRepository, turnRepository); + GameRoomService gameRoomService = new GameRoomService(roomDao); + + RoomDto findRoom = gameRoomService.findRoomById("1"); + + assertThat(findRoom).isEqualTo(room1); + } + + @Test + void 새로운_방을_만든다() { + RoomDao roomDao = new RoomMockDao(new HashMap<>(), new HashMap<>()); + GameRoomService gameRoomService = new GameRoomService(roomDao); + + assertThatCode(gameRoomService::createNewRoom) + .doesNotThrowAnyException(); + } +} From ad6cd5962b493c3e70a7631f55b72357b99c149b Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sun, 31 Mar 2024 23:22:23 +0900 Subject: [PATCH 65/94] =?UTF-8?q?remove:=20DAO=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/repository/PieceDaoTest.java | 66 ---------------------- src/test/java/repository/RoomDaoTest.java | 37 ------------ src/test/java/repository/TurnDaoTest.java | 25 -------- 3 files changed, 128 deletions(-) delete mode 100644 src/test/java/repository/PieceDaoTest.java delete mode 100644 src/test/java/repository/RoomDaoTest.java delete mode 100644 src/test/java/repository/TurnDaoTest.java diff --git a/src/test/java/repository/PieceDaoTest.java b/src/test/java/repository/PieceDaoTest.java deleted file mode 100644 index e3d50dd2714..00000000000 --- a/src/test/java/repository/PieceDaoTest.java +++ /dev/null @@ -1,66 +0,0 @@ -package repository; - -import dto.PieceDto; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -@SuppressWarnings("NonAsciiCharacters") -public class PieceDaoTest { - private final PieceDao pieceDao = new PieceDao(); - - @AfterEach - void rollback() { - pieceDao.deleteAll(); - } - - @Test - void 피스를_저장한다() { - final var pieceDto = new PieceDto("A", "3", "WHITE", "PAWN"); - - pieceDao.add(pieceDto); - PieceDto findPieceDto = pieceDao.findOne("A", "3"); - - assertThat(findPieceDto).isEqualTo(pieceDto); - } - - @Test - void 피스를_찾는다() { - final var pieceDto = new PieceDto("A", "3", "WHITE", "PAWN"); - pieceDao.add(pieceDto); - - PieceDto findPiece = pieceDao.findOne("A", "3"); - - assertThat(findPiece.color()).isEqualTo("WHITE"); - assertThat(findPiece.type()).isEqualTo("PAWN"); - } - - @Test - void 피스를_모두_찾는다() { - final var pieceDtoA = new PieceDto("A", "3", "WHITE", "PAWN"); - final var pieceDtoB = new PieceDto("B", "5", "BLACK", "PAWN"); - final var pieceDtoC = new PieceDto("C", "7", "BLACK", "KING"); - pieceDao.add(pieceDtoA); - pieceDao.add(pieceDtoB); - pieceDao.add(pieceDtoC); - - assertThat(pieceDao.findAll()) - .containsExactlyInAnyOrder(pieceDtoA, pieceDtoB, pieceDtoC); - } - - @Test - void 저장된_피스_개수를_센다() { - final var pieceDtoA = new PieceDto("A", "3", "WHITE", "PAWN"); - final var pieceDtoB = new PieceDto("B", "5", "BLACK", "PAWN"); - final var pieceDtoC = new PieceDto("C", "7", "BLACK", "KING"); - pieceDao.add(pieceDtoA); - pieceDao.add(pieceDtoB); - pieceDao.add(pieceDtoC); - - assertThat(pieceDao.hasRecords()).isTrue(); - } -} diff --git a/src/test/java/repository/RoomDaoTest.java b/src/test/java/repository/RoomDaoTest.java deleted file mode 100644 index b7845d8a25d..00000000000 --- a/src/test/java/repository/RoomDaoTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package repository; - -import dto.RoomDto; -import dto.TurnDto; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -@SuppressWarnings("NonAsciiCharacters") -class RoomDaoTest { - private final RoomDao roomDao = new RoomDao(); - private final TurnDao turnDao = new TurnDao(); - - @Test - void 새로운_방_번호를_생성한다() { - assertThat(roomDao.addNewRoom().isPresent()).isTrue(); - } - - @Test - void 활성화된_방을_모두_찾는다() { - roomDao.add(new RoomDto(1)); - roomDao.add(new RoomDto(2)); - roomDao.add(new RoomDto(3)); - turnDao.add(new TurnDto("WHITE", 1)); - turnDao.add(new TurnDto("GAMEOVER", 2)); - turnDao.add(new TurnDto("BLACK", 3)); - - List activeRoomAll = roomDao.findActiveRoomAll(); - - assertThat(activeRoomAll).containsExactlyInAnyOrder(new RoomDto(1), new RoomDto(3)); - } -} diff --git a/src/test/java/repository/TurnDaoTest.java b/src/test/java/repository/TurnDaoTest.java deleted file mode 100644 index 90cada99e79..00000000000 --- a/src/test/java/repository/TurnDaoTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package repository; - -import domain.piece.Color; -import dto.RoomDto; -import dto.TurnDto; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) -@SuppressWarnings("NonAsciiCharacters") -class TurnDaoTest { - @Test - void 턴을_저장한다() { - TurnDto whiteTurn = new TurnDto("WHITE", 1); - RoomDto roomDto = new RoomDto(whiteTurn.gameId()); - TurnDao turnDao = new TurnDao(); - - turnDao.update(whiteTurn); - - assertThat(turnDao.findTurnByGameId(roomDto).getTurn()).isEqualTo(Color.WHITE); - } -} From 75f0647d48edbe1e2f479dc8db75f3d338b5b87e Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sun, 31 Mar 2024 23:26:47 +0900 Subject: [PATCH 66/94] =?UTF-8?q?refactor:=20=EC=B2=B4=EC=8A=A4=20?= =?UTF-8?q?=EA=B2=8C=EC=9E=84=EA=B3=BC=20=EA=B2=8C=EC=9E=84=EB=B0=A9=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=20=EB=B6=84=EB=A6=AC,=20=EC=BB=A4?= =?UTF-8?q?=EB=A7=A8=EB=93=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 4 +- .../{ => game}/ChessGameController.java | 4 +- .../{ => game}/command/Command.java | 2 +- .../{ => game}/command/EndOnCommand.java | 2 +- .../{ => game}/command/MoveOnCommand.java | 2 +- .../{ => game}/command/StartOnCommand.java | 2 +- .../{ => game}/command/StatusOnCommand.java | 2 +- .../{ => room}/GameRoomController.java | 19 +--------- .../java/controller/room/command/Command.java | 8 ++++ .../room/command/NewRoomOnCommand.java | 25 +++++++++++++ .../room/command/SelectRoomOnCommand.java | 37 +++++++++++++++++++ src/main/java/view/InputView.java | 19 +++++++--- src/main/java/view/MessageResolver.java | 6 +-- ...{CommandType.java => GameCommandType.java} | 16 ++++---- .../java/view/command/RoomCommandType.java | 31 ++++++++++++++++ 15 files changed, 137 insertions(+), 42 deletions(-) rename src/main/java/controller/{ => game}/ChessGameController.java (95%) rename src/main/java/controller/{ => game}/command/Command.java (73%) rename src/main/java/controller/{ => game}/command/EndOnCommand.java (94%) rename src/main/java/controller/{ => game}/command/MoveOnCommand.java (97%) rename src/main/java/controller/{ => game}/command/StartOnCommand.java (94%) rename src/main/java/controller/{ => game}/command/StatusOnCommand.java (95%) rename src/main/java/controller/{ => room}/GameRoomController.java (65%) create mode 100644 src/main/java/controller/room/command/Command.java create mode 100644 src/main/java/controller/room/command/NewRoomOnCommand.java create mode 100644 src/main/java/controller/room/command/SelectRoomOnCommand.java rename src/main/java/view/command/{CommandType.java => GameCommandType.java} (64%) create mode 100644 src/main/java/view/command/RoomCommandType.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index b5b0786fbda..abd2d59f892 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,5 +1,5 @@ -import controller.ChessGameController; -import controller.GameRoomController; +import controller.game.ChessGameController; +import controller.room.GameRoomController; import dto.RoomDto; import service.ChessGameService; import service.GameRoomService; diff --git a/src/main/java/controller/ChessGameController.java b/src/main/java/controller/game/ChessGameController.java similarity index 95% rename from src/main/java/controller/ChessGameController.java rename to src/main/java/controller/game/ChessGameController.java index b7c50d8dfc7..0647554197c 100644 --- a/src/main/java/controller/ChessGameController.java +++ b/src/main/java/controller/game/ChessGameController.java @@ -1,4 +1,4 @@ -package controller; +package controller.game; import domain.ChessGame; import domain.board.ChessBoard; @@ -39,7 +39,7 @@ private ChessBoard initializeChessGame(RoomDto roomDto) { private void readCommandUntilValid() { try { - InputView.readCommand().execute(chessGame); + InputView.readGameCommand().execute(chessGame); } catch (Exception e) { OutputView.printErrorMessage(e); readCommandUntilValid(); diff --git a/src/main/java/controller/command/Command.java b/src/main/java/controller/game/command/Command.java similarity index 73% rename from src/main/java/controller/command/Command.java rename to src/main/java/controller/game/command/Command.java index 30ef616704d..5a537fc7762 100644 --- a/src/main/java/controller/command/Command.java +++ b/src/main/java/controller/game/command/Command.java @@ -1,4 +1,4 @@ -package controller.command; +package controller.game.command; import domain.ChessGame; diff --git a/src/main/java/controller/command/EndOnCommand.java b/src/main/java/controller/game/command/EndOnCommand.java similarity index 94% rename from src/main/java/controller/command/EndOnCommand.java rename to src/main/java/controller/game/command/EndOnCommand.java index 01c0000f85f..885d147eddc 100644 --- a/src/main/java/controller/command/EndOnCommand.java +++ b/src/main/java/controller/game/command/EndOnCommand.java @@ -1,4 +1,4 @@ -package controller.command; +package controller.game.command; import domain.ChessGame; diff --git a/src/main/java/controller/command/MoveOnCommand.java b/src/main/java/controller/game/command/MoveOnCommand.java similarity index 97% rename from src/main/java/controller/command/MoveOnCommand.java rename to src/main/java/controller/game/command/MoveOnCommand.java index a6b57970473..3398e44046d 100644 --- a/src/main/java/controller/command/MoveOnCommand.java +++ b/src/main/java/controller/game/command/MoveOnCommand.java @@ -1,4 +1,4 @@ -package controller.command; +package controller.game.command; import domain.ChessGame; import domain.board.Score; diff --git a/src/main/java/controller/command/StartOnCommand.java b/src/main/java/controller/game/command/StartOnCommand.java similarity index 94% rename from src/main/java/controller/command/StartOnCommand.java rename to src/main/java/controller/game/command/StartOnCommand.java index 17f5f67350f..a3598e6802d 100644 --- a/src/main/java/controller/command/StartOnCommand.java +++ b/src/main/java/controller/game/command/StartOnCommand.java @@ -1,4 +1,4 @@ -package controller.command; +package controller.game.command; import domain.ChessGame; import view.OutputView; diff --git a/src/main/java/controller/command/StatusOnCommand.java b/src/main/java/controller/game/command/StatusOnCommand.java similarity index 95% rename from src/main/java/controller/command/StatusOnCommand.java rename to src/main/java/controller/game/command/StatusOnCommand.java index 4ec96cd05b7..42bdeba5258 100644 --- a/src/main/java/controller/command/StatusOnCommand.java +++ b/src/main/java/controller/game/command/StatusOnCommand.java @@ -1,4 +1,4 @@ -package controller.command; +package controller.game.command; import domain.ChessGame; import domain.board.Score; diff --git a/src/main/java/controller/GameRoomController.java b/src/main/java/controller/room/GameRoomController.java similarity index 65% rename from src/main/java/controller/GameRoomController.java rename to src/main/java/controller/room/GameRoomController.java index 31e42b98ea4..13b2f222d1a 100644 --- a/src/main/java/controller/GameRoomController.java +++ b/src/main/java/controller/room/GameRoomController.java @@ -1,10 +1,9 @@ -package controller; +package controller.room; import dto.RoomDto; import service.GameRoomService; import view.InputView; import view.OutputView; -import view.command.CommandInput; import java.util.List; @@ -30,24 +29,10 @@ public RoomDto run() { private RoomDto readCommandUntilValid() { try { - return findRoom(); + return InputView.readRoomCommand().execute(roomService); } catch (IllegalArgumentException e) { System.out.println(e.getMessage()); return readCommandUntilValid(); } } - - private RoomDto findRoom() { - CommandInput commandInput = InputView.readCommandInput(); - - if (commandInput.prefix().equals("new")) { - return roomService.createNewRoom(); - } - if (commandInput.prefix().equals("room")) { - String roomId = commandInput.getArguments().get(0); - return roomService.findRoomById(roomId); - } - - throw new IllegalArgumentException("방을 찾을 수 없습니다."); - } } diff --git a/src/main/java/controller/room/command/Command.java b/src/main/java/controller/room/command/Command.java new file mode 100644 index 00000000000..13ac45d0f6b --- /dev/null +++ b/src/main/java/controller/room/command/Command.java @@ -0,0 +1,8 @@ +package controller.room.command; + +import dto.RoomDto; +import service.GameRoomService; + +public interface Command { + RoomDto execute(GameRoomService gameRoomService); +} diff --git a/src/main/java/controller/room/command/NewRoomOnCommand.java b/src/main/java/controller/room/command/NewRoomOnCommand.java new file mode 100644 index 00000000000..5711c1bd5ff --- /dev/null +++ b/src/main/java/controller/room/command/NewRoomOnCommand.java @@ -0,0 +1,25 @@ +package controller.room.command; + +import dto.RoomDto; +import service.GameRoomService; + +import java.util.List; + +public class NewRoomOnCommand implements Command { + private static final int ARGUMENT_SIZE = 0; + + public NewRoomOnCommand(final List arguments) { + validateArgumentSize(arguments); + } + + private void validateArgumentSize(final List arguments) { + if (arguments.size() != ARGUMENT_SIZE) { + throw new IllegalArgumentException(); + } + } + + @Override + public RoomDto execute(final GameRoomService gameRoomService) { + return gameRoomService.createNewRoom(); + } +} diff --git a/src/main/java/controller/room/command/SelectRoomOnCommand.java b/src/main/java/controller/room/command/SelectRoomOnCommand.java new file mode 100644 index 00000000000..4de8b9b7b7c --- /dev/null +++ b/src/main/java/controller/room/command/SelectRoomOnCommand.java @@ -0,0 +1,37 @@ +package controller.room.command; + +import dto.RoomDto; +import service.GameRoomService; + +import java.util.List; + +public class SelectRoomOnCommand implements Command { + private static final int ARGUMENT_SIZE = 1; + + private final String roomId; + + public SelectRoomOnCommand(final List arguments) { + validateArgumentSize(arguments); + validateRoomId(arguments.get(0)); + this.roomId = arguments.get(0); + } + + private void validateArgumentSize(final List arguments) { + if (arguments.size() != ARGUMENT_SIZE) { + throw new IllegalArgumentException(); + } + } + + private void validateRoomId(final String input) { + try { + Integer.parseInt(input); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(); + } + } + + @Override + public RoomDto execute(final GameRoomService gameRoomService) { + return gameRoomService.findRoomById(roomId); + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 7f1fdf0c26c..a1ce4c264a8 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,8 +1,8 @@ package view; -import controller.command.Command; import view.command.CommandInput; -import view.command.CommandType; +import view.command.GameCommandType; +import view.command.RoomCommandType; import java.util.Scanner; @@ -10,16 +10,25 @@ public class InputView { private static final Scanner SCANNER = new Scanner(System.in); private static final String WRONG_COMMAND_ERROR_MESSAGE = "잘못된 형식의 명령어입니다."; - public static Command readCommand() { + public static controller.game.command.Command readGameCommand() { try { CommandInput input = readCommandInput(); - return CommandType.getCommand(input); + return GameCommandType.getCommand(input); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(WRONG_COMMAND_ERROR_MESSAGE); } } - public static CommandInput readCommandInput() { + public static controller.room.command.Command readRoomCommand() { + try { + CommandInput input = readCommandInput(); + return RoomCommandType.getCommand(input); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException(WRONG_COMMAND_ERROR_MESSAGE); + } + } + + private static CommandInput readCommandInput() { return new CommandInput(SCANNER.nextLine()); } } diff --git a/src/main/java/view/MessageResolver.java b/src/main/java/view/MessageResolver.java index 3dd0d34ad90..f53b071badf 100644 --- a/src/main/java/view/MessageResolver.java +++ b/src/main/java/view/MessageResolver.java @@ -14,9 +14,9 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; -import static view.command.CommandType.END; -import static view.command.CommandType.MOVE; -import static view.command.CommandType.START; +import static view.command.GameCommandType.END; +import static view.command.GameCommandType.MOVE; +import static view.command.GameCommandType.START; public class MessageResolver { private static final String LINE_SEPARATOR = System.lineSeparator(); diff --git a/src/main/java/view/command/CommandType.java b/src/main/java/view/command/GameCommandType.java similarity index 64% rename from src/main/java/view/command/CommandType.java rename to src/main/java/view/command/GameCommandType.java index 15424f7f5f8..dbbac9a6f30 100644 --- a/src/main/java/view/command/CommandType.java +++ b/src/main/java/view/command/GameCommandType.java @@ -1,16 +1,16 @@ package view.command; -import controller.command.Command; -import controller.command.EndOnCommand; -import controller.command.MoveOnCommand; -import controller.command.StartOnCommand; -import controller.command.StatusOnCommand; +import controller.game.command.Command; +import controller.game.command.EndOnCommand; +import controller.game.command.MoveOnCommand; +import controller.game.command.StartOnCommand; +import controller.game.command.StatusOnCommand; import java.util.Arrays; import java.util.List; import java.util.function.Function; -public enum CommandType { +public enum GameCommandType { START("start", StartOnCommand::new), END("end", EndOnCommand::new), STATUS("status", StatusOnCommand::new), @@ -19,13 +19,13 @@ public enum CommandType { private final String command; private final Function, Command> mapper; - CommandType(final String command, final Function, Command> mapper) { + GameCommandType(final String command, final Function, Command> mapper) { this.command = command; this.mapper = mapper; } public static Command getCommand(final CommandInput input) { - final CommandType commandType = Arrays.stream(CommandType.values()) + final GameCommandType commandType = Arrays.stream(GameCommandType.values()) .filter(command -> input.prefix().equals(command.command)) .findFirst() .orElseThrow(IllegalArgumentException::new); diff --git a/src/main/java/view/command/RoomCommandType.java b/src/main/java/view/command/RoomCommandType.java new file mode 100644 index 00000000000..fdc02d642ac --- /dev/null +++ b/src/main/java/view/command/RoomCommandType.java @@ -0,0 +1,31 @@ +package view.command; + +import controller.room.command.Command; +import controller.room.command.NewRoomOnCommand; +import controller.room.command.SelectRoomOnCommand; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; + +public enum RoomCommandType { + NEW_ROOM("new", NewRoomOnCommand::new), + ROOM_SELECTION("room", SelectRoomOnCommand::new); + + private final String command; + private final Function, Command> mapper; + + RoomCommandType(final String command, final Function, Command> mapper) { + this.command = command; + this.mapper = mapper; + } + + public static Command getCommand(final CommandInput input) { + final RoomCommandType commandType = Arrays.stream(RoomCommandType.values()) + .filter(command -> input.prefix().equals(command.command)) + .findFirst() + .orElseThrow(IllegalArgumentException::new); + + return commandType.mapper.apply(input.getArguments()); + } +} From 30c0fe7b5c06722304ffe1e4a5a5aad747093a79 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Sun, 31 Mar 2024 23:57:19 +0900 Subject: [PATCH 67/94] =?UTF-8?q?fix:=20DB=EC=97=90=20=EC=A1=B4=EC=9E=AC?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=A9=B4=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D=ED=95=98=EB=8A=94=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/repository/GameStateDaoImpl.java | 7 +++---- src/main/java/repository/RoomDaoImpl.java | 7 +++---- src/main/java/service/GameRoomService.java | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/main/java/repository/GameStateDaoImpl.java b/src/main/java/repository/GameStateDaoImpl.java index a21c3c19355..7c380d7358d 100644 --- a/src/main/java/repository/GameStateDaoImpl.java +++ b/src/main/java/repository/GameStateDaoImpl.java @@ -16,10 +16,6 @@ public class GameStateDaoImpl implements GameStateDao { resultSet.getInt("game_id") ); - GameStateDaoImpl() { - this(new JdbcTemplate()); - } - public GameStateDaoImpl(final JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } @@ -32,6 +28,9 @@ public void add(final StateDto stateDto) { public Optional findByGameId(final int gameId) { final String query = "SELECT * FROM " + TABLE_NAME + " WHERE game_id = ? LIMIT 1"; final List turns = jdbcTemplate.executeAndGet(query, rowMapper, String.valueOf(gameId)); + if (turns.isEmpty()) { + return Optional.empty(); + } return Optional.ofNullable(turns.get(0)); } diff --git a/src/main/java/repository/RoomDaoImpl.java b/src/main/java/repository/RoomDaoImpl.java index 1da3b5accdf..30bb0b51978 100644 --- a/src/main/java/repository/RoomDaoImpl.java +++ b/src/main/java/repository/RoomDaoImpl.java @@ -16,10 +16,6 @@ public class RoomDaoImpl implements RoomDao { resultSet.getInt("room_id") ); - RoomDaoImpl() { - this(new JdbcTemplate()); - } - public RoomDaoImpl(final JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } @@ -47,6 +43,9 @@ public Optional addNewRoom() { public Optional find(final String roomId) { final String query = "SELECT * FROM " + TABLE_NAME + " WHERE room_id = ?"; final List roomDtos = jdbcTemplate.executeAndGet(query, rowMapper, roomId); + if (roomDtos.isEmpty()) { + return Optional.empty(); + } return Optional.of(roomDtos.get(0)); } diff --git a/src/main/java/service/GameRoomService.java b/src/main/java/service/GameRoomService.java index bbf1daf9d73..11b1fc7bf22 100644 --- a/src/main/java/service/GameRoomService.java +++ b/src/main/java/service/GameRoomService.java @@ -31,6 +31,6 @@ public RoomDto createNewRoom() { public RoomDto findRoomById(final String roomId) { Optional room = roomDao.find(roomId); - return room.orElseThrow(IllegalArgumentException::new); + return room.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 방입니다.")); } } From 50e75dceb47eca85be98fba8423db74daaeb3b92 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 1 Apr 2024 00:03:41 +0900 Subject: [PATCH 68/94] =?UTF-8?q?refactor:=20=EA=B2=8C=EC=9E=84=EB=B0=A9?= =?UTF-8?q?=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EB=B7=B0=20=EB=A1=9C=EC=A7=81=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/room/GameRoomController.java | 10 +++------- src/main/java/view/MessageResolver.java | 20 +++++++++++++++++++ src/main/java/view/OutputView.java | 12 ++++++----- .../java/view/command/RoomCommandType.java | 4 ++++ 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/main/java/controller/room/GameRoomController.java b/src/main/java/controller/room/GameRoomController.java index 13b2f222d1a..476d8655afb 100644 --- a/src/main/java/controller/room/GameRoomController.java +++ b/src/main/java/controller/room/GameRoomController.java @@ -16,14 +16,10 @@ public GameRoomController(final GameRoomService roomService) { public RoomDto run() { List rooms = roomService.loadActiveRoomAll(); - if (rooms.isEmpty()) { - System.out.println("방이 존재하지 않습니다. 새로운 방을 생성해 주세요."); - } else { - System.out.println("입장할 방을 선택해 주세요."); - OutputView.printActiveRoomAll(rooms); - } + OutputView.printGameRoomGuideMessage(rooms); + RoomDto roomDto = readCommandUntilValid(); - System.out.println(roomDto.room_id() + "번 방에 입장합니다."); + OutputView.printEnteringRoomMessage(roomDto); return roomDto; } diff --git a/src/main/java/view/MessageResolver.java b/src/main/java/view/MessageResolver.java index f53b071badf..bf6fad98c6b 100644 --- a/src/main/java/view/MessageResolver.java +++ b/src/main/java/view/MessageResolver.java @@ -7,6 +7,7 @@ import domain.position.File; import domain.position.Position; import domain.position.Rank; +import dto.RoomDto; import java.util.Collections; import java.util.List; @@ -17,6 +18,8 @@ import static view.command.GameCommandType.END; import static view.command.GameCommandType.MOVE; import static view.command.GameCommandType.START; +import static view.command.RoomCommandType.NEW_ROOM; +import static view.command.RoomCommandType.ROOM_SELECTION; public class MessageResolver { private static final String LINE_SEPARATOR = System.lineSeparator(); @@ -91,4 +94,21 @@ public String resolveWinner(final Score score) { } return "우승자는 BLACK입니다!"; } + + public String resolveRoomList(final List rooms) { + String newRoomMessage = String.format("> 새로운 방 생성 : %s", NEW_ROOM.message()); + if (rooms.isEmpty()) { + return newRoomMessage; + } + + String roomGuideHeaderMessage = String.format("> 입장할 방 선택 : %s 방번호 - 예 %s 1", ROOM_SELECTION.message(), ROOM_SELECTION.message()); + String roomListMessage = "> 방 목록 : " + rooms.stream() + .map(room -> String.valueOf(room.room_id())) + .collect(Collectors.joining(", ")); + return String.join(LINE_SEPARATOR, newRoomMessage, roomGuideHeaderMessage, roomListMessage); + } + + public String resolveEnteringRoomMessage(final RoomDto roomDto) { + return roomDto.room_id() + "번 방에 입장합니다."; + } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index aa0aaf9c703..a4d939e9349 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -23,7 +23,7 @@ public static void printScore(Score score) { System.out.println(scoreMessage); } - public static void printWinner(final Score score) { + public static void printWinner(Score score) { System.out.println(messageResolver.resolveWinner(score)); } @@ -31,9 +31,11 @@ public static void printErrorMessage(Exception e) { System.out.println(e.getMessage()); } - public static void printActiveRoomAll(final List rooms) { - for (RoomDto room : rooms) { - System.out.println("Room " + room.room_id()); - } + public static void printGameRoomGuideMessage(List rooms) { + System.out.println(messageResolver.resolveRoomList(rooms)); + } + + public static void printEnteringRoomMessage(RoomDto roomDto) { + System.out.println(messageResolver.resolveEnteringRoomMessage(roomDto)); } } diff --git a/src/main/java/view/command/RoomCommandType.java b/src/main/java/view/command/RoomCommandType.java index fdc02d642ac..807332e9bfe 100644 --- a/src/main/java/view/command/RoomCommandType.java +++ b/src/main/java/view/command/RoomCommandType.java @@ -28,4 +28,8 @@ public static Command getCommand(final CommandInput input) { return commandType.mapper.apply(input.getArguments()); } + + public String message() { + return this.command; + } } From 742370373233fc01a5019a279015cfb1fcb95750 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 1 Apr 2024 00:07:24 +0900 Subject: [PATCH 69/94] =?UTF-8?q?refactor:=20application=EC=97=90=20?= =?UTF-8?q?=EC=A1=B4=EC=9E=AC=ED=95=98=EB=8A=94=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=EC=9D=84=20MainController=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Application.java | 15 +++------------ src/main/java/controller/MainController.java | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 12 deletions(-) create mode 100644 src/main/java/controller/MainController.java diff --git a/src/main/java/Application.java b/src/main/java/Application.java index abd2d59f892..1499d1f1f82 100644 --- a/src/main/java/Application.java +++ b/src/main/java/Application.java @@ -1,17 +1,8 @@ -import controller.game.ChessGameController; -import controller.room.GameRoomController; -import dto.RoomDto; -import service.ChessGameService; -import service.GameRoomService; +import controller.MainController; public class Application { public static void main(String[] args) { - GameRoomController gameRoomController = new GameRoomController(new GameRoomService()); - ChessGameController chessGameController = new ChessGameController(new ChessGameService()); - - while (true) { - RoomDto roomDto = gameRoomController.run(); - chessGameController.start(roomDto); - } + MainController mainController = new MainController(); + mainController.run(); } } diff --git a/src/main/java/controller/MainController.java b/src/main/java/controller/MainController.java new file mode 100644 index 00000000000..8967b0e91fc --- /dev/null +++ b/src/main/java/controller/MainController.java @@ -0,0 +1,19 @@ +package controller; + +import controller.game.ChessGameController; +import controller.room.GameRoomController; +import dto.RoomDto; +import service.ChessGameService; +import service.GameRoomService; + +public class MainController { + private final GameRoomController gameRoomController = new GameRoomController(new GameRoomService()); + private final ChessGameController chessGameController = new ChessGameController(new ChessGameService()); + + public void run() { + while (true) { + RoomDto roomDto = gameRoomController.run(); + chessGameController.start(roomDto); + } + } +} From 76752dd9d52c52e919fc9f681d03050a19832c2a Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 1 Apr 2024 00:35:17 +0900 Subject: [PATCH 70/94] =?UTF-8?q?fix:=20=EC=9E=98=EB=AA=BB=EB=90=9C=20?= =?UTF-8?q?=EB=B0=A9=EB=B2=88=ED=98=B8=20=EC=9E=85=EB=A0=A5=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/controller/room/GameRoomController.java | 12 ++++++------ .../controller/room/command/NewRoomOnCommand.java | 2 +- .../room/command/SelectRoomOnCommand.java | 15 ++++++++++++--- src/main/java/view/InputView.java | 8 +++++--- src/main/java/view/command/RoomCommandType.java | 11 ++++++----- 5 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/main/java/controller/room/GameRoomController.java b/src/main/java/controller/room/GameRoomController.java index 476d8655afb..82fe34862db 100644 --- a/src/main/java/controller/room/GameRoomController.java +++ b/src/main/java/controller/room/GameRoomController.java @@ -10,7 +10,7 @@ public class GameRoomController { private final GameRoomService roomService; - public GameRoomController(final GameRoomService roomService) { + public GameRoomController(GameRoomService roomService) { this.roomService = roomService; } @@ -18,17 +18,17 @@ public RoomDto run() { List rooms = roomService.loadActiveRoomAll(); OutputView.printGameRoomGuideMessage(rooms); - RoomDto roomDto = readCommandUntilValid(); + RoomDto roomDto = readCommandUntilValid(rooms); OutputView.printEnteringRoomMessage(roomDto); return roomDto; } - private RoomDto readCommandUntilValid() { + private RoomDto readCommandUntilValid(List rooms) { try { - return InputView.readRoomCommand().execute(roomService); + return InputView.readRoomCommand(rooms).execute(roomService); } catch (IllegalArgumentException e) { - System.out.println(e.getMessage()); - return readCommandUntilValid(); + OutputView.printErrorMessage(e); + return readCommandUntilValid(rooms); } } } diff --git a/src/main/java/controller/room/command/NewRoomOnCommand.java b/src/main/java/controller/room/command/NewRoomOnCommand.java index 5711c1bd5ff..7495483716a 100644 --- a/src/main/java/controller/room/command/NewRoomOnCommand.java +++ b/src/main/java/controller/room/command/NewRoomOnCommand.java @@ -8,7 +8,7 @@ public class NewRoomOnCommand implements Command { private static final int ARGUMENT_SIZE = 0; - public NewRoomOnCommand(final List arguments) { + public NewRoomOnCommand(final List arguments, final List rooms) { validateArgumentSize(arguments); } diff --git a/src/main/java/controller/room/command/SelectRoomOnCommand.java b/src/main/java/controller/room/command/SelectRoomOnCommand.java index 4de8b9b7b7c..23cd3aa6680 100644 --- a/src/main/java/controller/room/command/SelectRoomOnCommand.java +++ b/src/main/java/controller/room/command/SelectRoomOnCommand.java @@ -10,9 +10,10 @@ public class SelectRoomOnCommand implements Command { private final String roomId; - public SelectRoomOnCommand(final List arguments) { + public SelectRoomOnCommand(final List arguments, final List validRooms) { validateArgumentSize(arguments); - validateRoomId(arguments.get(0)); + validateRoomIdFormat(arguments.get(0)); + validateRoomIdRunning(validRooms, arguments.get(0)); this.roomId = arguments.get(0); } @@ -22,7 +23,7 @@ private void validateArgumentSize(final List arguments) { } } - private void validateRoomId(final String input) { + private void validateRoomIdFormat(final String input) { try { Integer.parseInt(input); } catch (NumberFormatException e) { @@ -30,6 +31,14 @@ private void validateRoomId(final String input) { } } + private void validateRoomIdRunning(final List validRooms, final String input) { + boolean isRunningRoomNotFound = validRooms.stream() + .noneMatch(room -> room.room_id() == Integer.parseInt(input)); + if (isRunningRoomNotFound) { + throw new IllegalArgumentException(); + } + } + @Override public RoomDto execute(final GameRoomService gameRoomService) { return gameRoomService.findRoomById(roomId); diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index a1ce4c264a8..c075068f619 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,14 +1,16 @@ package view; +import dto.RoomDto; import view.command.CommandInput; import view.command.GameCommandType; import view.command.RoomCommandType; +import java.util.List; import java.util.Scanner; public class InputView { private static final Scanner SCANNER = new Scanner(System.in); - private static final String WRONG_COMMAND_ERROR_MESSAGE = "잘못된 형식의 명령어입니다."; + private static final String WRONG_COMMAND_ERROR_MESSAGE = "잘못된 명령어입니다."; public static controller.game.command.Command readGameCommand() { try { @@ -19,10 +21,10 @@ public static controller.game.command.Command readGameCommand() { } } - public static controller.room.command.Command readRoomCommand() { + public static controller.room.command.Command readRoomCommand(List rooms) { try { CommandInput input = readCommandInput(); - return RoomCommandType.getCommand(input); + return RoomCommandType.getCommand(input, rooms); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(WRONG_COMMAND_ERROR_MESSAGE); } diff --git a/src/main/java/view/command/RoomCommandType.java b/src/main/java/view/command/RoomCommandType.java index 807332e9bfe..befbd1a8d9a 100644 --- a/src/main/java/view/command/RoomCommandType.java +++ b/src/main/java/view/command/RoomCommandType.java @@ -3,30 +3,31 @@ import controller.room.command.Command; import controller.room.command.NewRoomOnCommand; import controller.room.command.SelectRoomOnCommand; +import dto.RoomDto; import java.util.Arrays; import java.util.List; -import java.util.function.Function; +import java.util.function.BiFunction; public enum RoomCommandType { NEW_ROOM("new", NewRoomOnCommand::new), ROOM_SELECTION("room", SelectRoomOnCommand::new); private final String command; - private final Function, Command> mapper; + private final BiFunction, List, Command> mapper; - RoomCommandType(final String command, final Function, Command> mapper) { + RoomCommandType(final String command, final BiFunction, List, Command> mapper) { this.command = command; this.mapper = mapper; } - public static Command getCommand(final CommandInput input) { + public static Command getCommand(final CommandInput input, final List rooms) { final RoomCommandType commandType = Arrays.stream(RoomCommandType.values()) .filter(command -> input.prefix().equals(command.command)) .findFirst() .orElseThrow(IllegalArgumentException::new); - return commandType.mapper.apply(input.getArguments()); + return commandType.mapper.apply(input.getArguments(), rooms); } public String message() { From 23f426092882c25ab177efdbf6381ef1adf2c28e Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 1 Apr 2024 00:44:11 +0900 Subject: [PATCH 71/94] =?UTF-8?q?refactor:=20=EB=AA=A8=EB=93=A0=20?= =?UTF-8?q?=EC=B6=9C=EB=A0=A5=20=EB=92=A4=EC=97=90=20=EA=B0=9C=ED=96=89=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/OutputView.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index a4d939e9349..e19f5555146 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -8,34 +8,39 @@ public class OutputView { private static final MessageResolver messageResolver = new MessageResolver(); + public static final String LINE_SEPARATOR = System.lineSeparator(); public static void printGameGuideMessage() { - System.out.println(messageResolver.resolveGameStartMessage()); + printWithLineSeparator(messageResolver.resolveGameStartMessage()); } public static void printBoard(ChessBoard board) { String boardMessage = messageResolver.resolveBoard(board); - System.out.println(boardMessage); + printWithLineSeparator(boardMessage); } public static void printScore(Score score) { String scoreMessage = messageResolver.resolveScore(score); - System.out.println(scoreMessage); + printWithLineSeparator(scoreMessage); } public static void printWinner(Score score) { - System.out.println(messageResolver.resolveWinner(score)); + printWithLineSeparator(messageResolver.resolveWinner(score)); } public static void printErrorMessage(Exception e) { - System.out.println(e.getMessage()); + printWithLineSeparator(e.getMessage()); } public static void printGameRoomGuideMessage(List rooms) { - System.out.println(messageResolver.resolveRoomList(rooms)); + printWithLineSeparator(messageResolver.resolveRoomList(rooms)); } public static void printEnteringRoomMessage(RoomDto roomDto) { - System.out.println(messageResolver.resolveEnteringRoomMessage(roomDto)); + printWithLineSeparator(messageResolver.resolveEnteringRoomMessage(roomDto)); + } + + private static void printWithLineSeparator(String message) { + System.out.println(message + LINE_SEPARATOR); } } From 9f6b2e1415ca0ec3d65266aa4933d87e54b8d918 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 1 Apr 2024 01:30:31 +0900 Subject: [PATCH 72/94] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/room/command/NewRoomOnCommand.java | 2 +- src/main/java/view/command/RoomCommandType.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/controller/room/command/NewRoomOnCommand.java b/src/main/java/controller/room/command/NewRoomOnCommand.java index 7495483716a..5711c1bd5ff 100644 --- a/src/main/java/controller/room/command/NewRoomOnCommand.java +++ b/src/main/java/controller/room/command/NewRoomOnCommand.java @@ -8,7 +8,7 @@ public class NewRoomOnCommand implements Command { private static final int ARGUMENT_SIZE = 0; - public NewRoomOnCommand(final List arguments, final List rooms) { + public NewRoomOnCommand(final List arguments) { validateArgumentSize(arguments); } diff --git a/src/main/java/view/command/RoomCommandType.java b/src/main/java/view/command/RoomCommandType.java index befbd1a8d9a..30a52b7a9ff 100644 --- a/src/main/java/view/command/RoomCommandType.java +++ b/src/main/java/view/command/RoomCommandType.java @@ -10,7 +10,7 @@ import java.util.function.BiFunction; public enum RoomCommandType { - NEW_ROOM("new", NewRoomOnCommand::new), + NEW_ROOM("new", (arguments, rooms) -> new NewRoomOnCommand(arguments)), ROOM_SELECTION("room", SelectRoomOnCommand::new); private final String command; From ed7c33bd3190ca02b3b16d4cff6649e7a69c7576 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 1 Apr 2024 08:43:45 +0900 Subject: [PATCH 73/94] =?UTF-8?q?refactor:=20var=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/db/JdbcTemplate.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/db/JdbcTemplate.java b/src/main/java/db/JdbcTemplate.java index d94d5c59c6c..4225c02a3c2 100644 --- a/src/main/java/db/JdbcTemplate.java +++ b/src/main/java/db/JdbcTemplate.java @@ -1,5 +1,6 @@ package db; +import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -14,8 +15,8 @@ public JdbcTemplate() { } public void execute(final String query, final String... parameters) { - try (final var connection = connectionManager.getConnection(); - final var preparedStatement = connection.prepareStatement(query)) { + try (final Connection connection = connectionManager.getConnection(); + final PreparedStatement preparedStatement = connection.prepareStatement(query)) { setParameters(preparedStatement, parameters); preparedStatement.executeUpdate(); } catch (final SQLException e) { @@ -24,8 +25,8 @@ public void execute(final String query, final String... parameters) { } public List executeAndGet(final String query, final RowMapper mapper, final String... parameters) { - try (final var connection = connectionManager.getConnection(); - final var preparedStatement = connection.prepareStatement(query)) { + try (final Connection connection = connectionManager.getConnection(); + final PreparedStatement preparedStatement = connection.prepareStatement(query)) { setParameters(preparedStatement, parameters); return resolveResult(mapper, preparedStatement); } catch (final SQLException e) { From 153a5a1b157b9af399f9c31fbcc738ef02c6239a Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 1 Apr 2024 15:13:07 +0900 Subject: [PATCH 74/94] =?UTF-8?q?refactor:=20Controller=EC=9D=98=20?= =?UTF-8?q?=EB=B9=84=EC=A6=88=EB=8B=88=EC=8A=A4=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=EC=9D=84=20Service=EB=A1=9C=20=EC=9D=B4=EC=A0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/game/ChessGameController.java | 38 +++---------- src/main/java/service/ChessGameService.java | 31 +++++++++-- .../java/service/ChessGameServiceTest.java | 55 +++++++++++-------- 3 files changed, 65 insertions(+), 59 deletions(-) diff --git a/src/main/java/controller/game/ChessGameController.java b/src/main/java/controller/game/ChessGameController.java index 0647554197c..4de15432dc2 100644 --- a/src/main/java/controller/game/ChessGameController.java +++ b/src/main/java/controller/game/ChessGameController.java @@ -1,57 +1,33 @@ package controller.game; import domain.ChessGame; -import domain.board.ChessBoard; -import domain.board.ChessBoardFactory; import dto.RoomDto; -import dto.StateDto; import service.ChessGameService; import view.InputView; import view.OutputView; -import java.util.NoSuchElementException; - public class ChessGameController { private final ChessGameService chessGameService; - private ChessGame chessGame; - public ChessGameController(final ChessGameService chessGameService) { + public ChessGameController(ChessGameService chessGameService) { this.chessGameService = chessGameService; } - public void start(final RoomDto roomDto) { - chessGame = new ChessGame(initializeChessGame(roomDto)); + public void start(RoomDto roomDto) { + ChessGame chessGame = chessGameService.initializeChessGame(roomDto); OutputView.printGameGuideMessage(); while (chessGame.isPlaying()) { - readCommandUntilValid(); - } - updateGameStatus(roomDto); - } - - private ChessBoard initializeChessGame(RoomDto roomDto) { - try { - StateDto stateDto = chessGameService.loadPreviousState(roomDto); - return ChessBoardFactory.loadPreviousChessBoard(chessGameService.loadPreviousPieces(roomDto), stateDto.getState()); - } catch (NoSuchElementException e) { - return ChessBoardFactory.createInitialChessBoard(); + readCommandUntilValid(chessGame); } + chessGameService.saveChessGame(chessGame, roomDto); } - private void readCommandUntilValid() { + private void readCommandUntilValid(ChessGame chessGame) { try { InputView.readGameCommand().execute(chessGame); } catch (Exception e) { OutputView.printErrorMessage(e); - readCommandUntilValid(); - } - } - - private void updateGameStatus(final RoomDto roomDto) { - if (chessGame.isGameOver()) { - chessGameService.updateState(new StateDto("GAMEOVER", roomDto.room_id())); - return; + readCommandUntilValid(chessGame); } - chessGameService.updatePieces(roomDto, chessGame.getBoard().getPieces()); - chessGameService.updateState(new StateDto(chessGame.getTurn().name(), roomDto.room_id())); } } diff --git a/src/main/java/service/ChessGameService.java b/src/main/java/service/ChessGameService.java index 85cd84a4c44..9ffa9c3f702 100644 --- a/src/main/java/service/ChessGameService.java +++ b/src/main/java/service/ChessGameService.java @@ -1,13 +1,15 @@ package service; import db.JdbcTemplate; +import domain.ChessGame; +import domain.board.ChessBoardFactory; import dto.PieceDto; import dto.RoomDto; import dto.StateDto; import repository.GameStateDao; +import repository.GameStateDaoImpl; import repository.PieceDao; import repository.PieceDaoImpl; -import repository.GameStateDaoImpl; import java.util.List; import java.util.NoSuchElementException; @@ -27,23 +29,42 @@ public ChessGameService() { this.gameStateDao = new GameStateDaoImpl(jdbcTemplate); } - public List loadPreviousPieces(final RoomDto roomDto) { + public ChessGame initializeChessGame(RoomDto roomDto) { + try { + StateDto stateDto = loadPreviousState(roomDto); + return new ChessGame(ChessBoardFactory.loadPreviousChessBoard( + loadPreviousPieces(roomDto), stateDto.getState())); + } catch (NoSuchElementException e) { + return new ChessGame(ChessBoardFactory.createInitialChessBoard()); + } + } + + public void saveChessGame(ChessGame chessGame, RoomDto roomDto) { + if (chessGame.isGameOver()) { + updateState(new StateDto("GAMEOVER", roomDto.room_id())); + return; + } + updatePieces(roomDto, chessGame.getBoard().getPieces()); + updateState(new StateDto(chessGame.getTurn().name(), roomDto.room_id())); + } + + private List loadPreviousPieces(final RoomDto roomDto) { return pieceDao.findPieceByGameId(roomDto.room_id()); } - public StateDto loadPreviousState(final RoomDto roomDto) { + private StateDto loadPreviousState(final RoomDto roomDto) { return gameStateDao.findByGameId(roomDto.room_id()) .orElseThrow(NoSuchElementException::new); } - public void updatePieces(final RoomDto roomDto, final List pieceDtos) { + private void updatePieces(final RoomDto roomDto, final List pieceDtos) { pieceDao.deleteAllByGameId(roomDto.room_id()); for (PieceDto pieceDto : pieceDtos) { pieceDao.add(roomDto, pieceDto); } } - public void updateState(final StateDto stateDto) { + private void updateState(final StateDto stateDto) { gameStateDao.deleteByGameId(stateDto.gameId()); gameStateDao.add(stateDto); } diff --git a/src/test/java/service/ChessGameServiceTest.java b/src/test/java/service/ChessGameServiceTest.java index b96278ddf80..2195227015f 100644 --- a/src/test/java/service/ChessGameServiceTest.java +++ b/src/test/java/service/ChessGameServiceTest.java @@ -1,6 +1,12 @@ package service; +import domain.ChessGame; +import domain.board.ChessBoard; import domain.piece.Color; +import domain.piece.Piece; +import domain.piece.nonpawn.King; +import domain.piece.pawn.WhitePawn; +import domain.position.Position; import dto.PieceDto; import dto.RoomDto; import dto.StateDto; @@ -14,7 +20,7 @@ import repository.PieceDao; import repository.PieceMockDao; -import java.util.List; +import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; @@ -24,8 +30,6 @@ class ChessGameServiceTest { private static final PieceDto A2WhitePawn = new PieceDto("A", "2", "WHITE", "PAWN"); private static final PieceDto B2WhitePawn = new PieceDto("B", "2", "WHITE", "PAWN"); private static final PieceDto C2WhitePawn = new PieceDto("C", "2", "WHITE", "PAWN"); - private static final StateDto whiteTurn = new StateDto("WHITE", 1); - private static final StateDto blackTurn = new StateDto("BLACK", 2); private static final RoomDto room1 = new RoomDto(1); private final PieceDao pieceDao = new PieceMockDao(); @@ -37,7 +41,7 @@ void setData() { pieceDao.add(room1, A2WhitePawn); pieceDao.add(room1, B2WhitePawn); pieceDao.add(room1, C2WhitePawn); - gameStateDao.add(whiteTurn); + gameStateDao.add(new StateDto("WHITE", 1)); } @AfterEach @@ -48,36 +52,41 @@ void rollback() { @Test void 이전_게임의_피스_데이터를_불러온다() { - assertThat(chessGameService.loadPreviousPieces(room1)) + ChessGame chessGame = chessGameService.initializeChessGame(room1); + + assertThat(chessGame.getBoard().getPieces()) .containsExactlyInAnyOrder(A2WhitePawn, B2WhitePawn, C2WhitePawn); } @Test void 이전_게임의_턴_데이터를_불러온다() { - assertThat(chessGameService.loadPreviousState(room1).getState()) + ChessGame chessGame = chessGameService.initializeChessGame(room1); + + assertThat(chessGame.getTurn()) .isEqualTo(Color.WHITE); } @Test - void 피스_데이터를_갱신한다() { + void 게임_데이터를_갱신한다() { RoomDto roomDto = room1; - PieceDto A3WhitePawn = new PieceDto("A", "3", "WHITE", "PAWN"); - PieceDto B3WhitePawn = new PieceDto("B", "3", "WHITE", "PAWN"); - PieceDto C3WhitePawn = new PieceDto("C", "3", "WHITE", "PAWN"); - - chessGameService.updatePieces(roomDto, List.of(A3WhitePawn, B3WhitePawn, C3WhitePawn)); - - assertThat(chessGameService.loadPreviousPieces(roomDto)) - .containsExactlyInAnyOrder(A3WhitePawn, B3WhitePawn, C3WhitePawn); - } - - @Test - void 턴_데이터를_갱신한다() { - RoomDto room = new RoomDto(blackTurn.gameId()); + Position A3 = new Position("A3"); + Position B3 = new Position("B3"); + Position C3 = new Position("C3"); + Map pawnMap = Map.of( + A3, new King(Color.WHITE), + B3, new King(Color.BLACK), + C3, new WhitePawn()); + ChessGame chessGame = new ChessGame(new ChessBoard(pawnMap)); - chessGameService.updateState(blackTurn); + chessGameService.saveChessGame(chessGame, roomDto); + chessGame = chessGameService.initializeChessGame(roomDto); - assertThat(chessGameService.loadPreviousState(room).getState()) - .isEqualTo(Color.BLACK); + assertThat(chessGame.getBoard().getPieces()) + .containsExactlyInAnyOrder( + PieceDto.of(A3, new King(Color.WHITE)), + PieceDto.of(B3, new King(Color.BLACK)), + PieceDto.of(C3, new WhitePawn())); + assertThat(chessGame.getBoard().getTurn()) + .isEqualTo(Color.WHITE); } } From 8cce0279fb9534bd78943ec9ea4c9d0d248aa2e3 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 1 Apr 2024 15:14:54 +0900 Subject: [PATCH 75/94] =?UTF-8?q?refactor:=20Postion=EC=97=90=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EC=83=9D=EC=84=B1=EC=9E=90=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/position/Position.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/java/domain/position/Position.java b/src/main/java/domain/position/Position.java index de8d6deaf86..adb8e67c9fa 100644 --- a/src/main/java/domain/position/Position.java +++ b/src/main/java/domain/position/Position.java @@ -7,11 +7,8 @@ public class Position { private final Rank rank; public Position(final String fileAndRank) { - this(fileAndRank.substring(0, 1), Integer.parseInt(fileAndRank.substring(1))); - } - - private Position(final String file, final int rank) { - this(File.fromName(file), Rank.fromNumber(rank)); + this(File.fromName(fileAndRank.substring(0, 1)), + Rank.fromNumber(Integer.parseInt(fileAndRank.substring(1)))); } public Position(final File file, final Rank rank) { From 928da168e81ddc7cda9c14803735744ca3457f6a Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 1 Apr 2024 15:29:36 +0900 Subject: [PATCH 76/94] =?UTF-8?q?refactor:=20service=20=EB=8B=A8=EC=97=90?= =?UTF-8?q?=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EC=9E=90=20=EC=82=AD=EC=A0=9C,=20=EB=82=B4=EB=B6=80=20?= =?UTF-8?q?=ED=95=84=EB=93=9C=EB=A5=BC=20=EC=9C=84=EB=B6=80=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=A3=BC=EC=9E=85=20=EB=B0=9B=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/MainController.java | 8 ++++++-- src/main/java/repository/GameStateDaoImpl.java | 6 +----- src/main/java/repository/PieceDaoImpl.java | 9 ++------- src/main/java/repository/RoomDaoImpl.java | 6 +----- src/main/java/service/ChessGameService.java | 11 +---------- src/main/java/service/GameRoomService.java | 9 +-------- 6 files changed, 12 insertions(+), 37 deletions(-) diff --git a/src/main/java/controller/MainController.java b/src/main/java/controller/MainController.java index 8967b0e91fc..d22128e9a96 100644 --- a/src/main/java/controller/MainController.java +++ b/src/main/java/controller/MainController.java @@ -3,12 +3,16 @@ import controller.game.ChessGameController; import controller.room.GameRoomController; import dto.RoomDto; +import repository.GameStateDaoImpl; +import repository.PieceDaoImpl; +import repository.RoomDaoImpl; import service.ChessGameService; import service.GameRoomService; public class MainController { - private final GameRoomController gameRoomController = new GameRoomController(new GameRoomService()); - private final ChessGameController chessGameController = new ChessGameController(new ChessGameService()); + private final GameRoomController gameRoomController = new GameRoomController(new GameRoomService(new RoomDaoImpl())); + private final ChessGameController chessGameController = new ChessGameController(new ChessGameService( + new PieceDaoImpl(), new GameStateDaoImpl())); public void run() { while (true) { diff --git a/src/main/java/repository/GameStateDaoImpl.java b/src/main/java/repository/GameStateDaoImpl.java index 7c380d7358d..99c89d69058 100644 --- a/src/main/java/repository/GameStateDaoImpl.java +++ b/src/main/java/repository/GameStateDaoImpl.java @@ -10,16 +10,12 @@ public class GameStateDaoImpl implements GameStateDao { private static final String TABLE_NAME = "game_states"; - private final JdbcTemplate jdbcTemplate; + private final JdbcTemplate jdbcTemplate = new JdbcTemplate(); private final RowMapper rowMapper = (resultSet) -> new StateDto( resultSet.getString("state"), resultSet.getInt("game_id") ); - public GameStateDaoImpl(final JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - public void add(final StateDto stateDto) { final String query = "INSERT INTO " + TABLE_NAME + " VALUES (?, ?)"; jdbcTemplate.execute(query, String.valueOf(stateDto.gameId()), stateDto.state()); diff --git a/src/main/java/repository/PieceDaoImpl.java b/src/main/java/repository/PieceDaoImpl.java index 4d9a7df9f80..634451f8e8e 100644 --- a/src/main/java/repository/PieceDaoImpl.java +++ b/src/main/java/repository/PieceDaoImpl.java @@ -10,7 +10,7 @@ public class PieceDaoImpl implements PieceDao { private static final String TABLE_NAME = "pieces"; - private final JdbcTemplate jdbcTemplate; + private final JdbcTemplate jdbcTemplate = new JdbcTemplate(); private final RowMapper rowMapper = (resultSet) -> new PieceDto( resultSet.getString("board_file"), resultSet.getString("board_rank"), @@ -18,12 +18,7 @@ public class PieceDaoImpl implements PieceDao { resultSet.getString("type") ); - PieceDaoImpl() { - this(new JdbcTemplate()); - } - - public PieceDaoImpl(final JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; + public PieceDaoImpl() { } public void add(final RoomDto room, final PieceDto piece) { diff --git a/src/main/java/repository/RoomDaoImpl.java b/src/main/java/repository/RoomDaoImpl.java index 30bb0b51978..105aa3dd937 100644 --- a/src/main/java/repository/RoomDaoImpl.java +++ b/src/main/java/repository/RoomDaoImpl.java @@ -11,15 +11,11 @@ public class RoomDaoImpl implements RoomDao { private static final String TABLE_NAME = "rooms"; private static final String GAME_STATUES_TABLE_NAME = "game_states"; - private final JdbcTemplate jdbcTemplate; + private final JdbcTemplate jdbcTemplate = new JdbcTemplate(); private final RowMapper rowMapper = (resultSet) -> new RoomDto( resultSet.getInt("room_id") ); - public RoomDaoImpl(final JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - public void add(final RoomDto roomDto) { final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (?)"; jdbcTemplate.execute(insertQuery, "" + roomDto.room_id()); diff --git a/src/main/java/service/ChessGameService.java b/src/main/java/service/ChessGameService.java index 9ffa9c3f702..710cafa0291 100644 --- a/src/main/java/service/ChessGameService.java +++ b/src/main/java/service/ChessGameService.java @@ -1,15 +1,12 @@ package service; -import db.JdbcTemplate; import domain.ChessGame; import domain.board.ChessBoardFactory; import dto.PieceDto; import dto.RoomDto; import dto.StateDto; import repository.GameStateDao; -import repository.GameStateDaoImpl; import repository.PieceDao; -import repository.PieceDaoImpl; import java.util.List; import java.util.NoSuchElementException; @@ -18,17 +15,11 @@ public class ChessGameService { private final PieceDao pieceDao; private final GameStateDao gameStateDao; - ChessGameService(final PieceDao pieceDao, final GameStateDao gameStateDao) { + public ChessGameService(final PieceDao pieceDao, final GameStateDao gameStateDao) { this.pieceDao = pieceDao; this.gameStateDao = gameStateDao; } - public ChessGameService() { - final JdbcTemplate jdbcTemplate = new JdbcTemplate(); - this.pieceDao = new PieceDaoImpl(jdbcTemplate); - this.gameStateDao = new GameStateDaoImpl(jdbcTemplate); - } - public ChessGame initializeChessGame(RoomDto roomDto) { try { StateDto stateDto = loadPreviousState(roomDto); diff --git a/src/main/java/service/GameRoomService.java b/src/main/java/service/GameRoomService.java index 11b1fc7bf22..82a9ed5a177 100644 --- a/src/main/java/service/GameRoomService.java +++ b/src/main/java/service/GameRoomService.java @@ -1,9 +1,7 @@ package service; -import db.JdbcTemplate; import dto.RoomDto; import repository.RoomDao; -import repository.RoomDaoImpl; import java.util.List; import java.util.Optional; @@ -11,15 +9,10 @@ public class GameRoomService { private final RoomDao roomDao; - GameRoomService(final RoomDao roomDao) { + public GameRoomService(final RoomDao roomDao) { this.roomDao = roomDao; } - public GameRoomService() { - final JdbcTemplate jdbcTemplate = new JdbcTemplate(); - this.roomDao = new RoomDaoImpl(jdbcTemplate); - } - public List loadActiveRoomAll() { return roomDao.findActiveRoomAll(); } From 072b05293a28e82f2279166d5406f8ef3584ad2e Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 1 Apr 2024 15:56:50 +0900 Subject: [PATCH 77/94] =?UTF-8?q?chore:=20=ED=8C=A8=ED=82=A4=EC=A7=80=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/MainController.java | 6 +++--- src/main/java/{db => database}/ConnectionManager.java | 2 +- src/main/java/{db => database}/JdbcTemplate.java | 2 +- src/main/java/{db => database}/RowMapper.java | 2 +- .../java/{repository => database/dao}/GameStateDao.java | 2 +- .../java/{repository => database/dao}/GameStateDaoImpl.java | 6 +++--- src/main/java/{repository => database/dao}/PieceDao.java | 2 +- .../java/{repository => database/dao}/PieceDaoImpl.java | 6 +++--- src/main/java/{repository => database/dao}/RoomDao.java | 2 +- src/main/java/{repository => database/dao}/RoomDaoImpl.java | 6 +++--- src/main/java/service/ChessGameService.java | 4 ++-- src/main/java/service/GameRoomService.java | 2 +- src/test/java/db/ConnectionManagerTest.java | 1 + src/test/java/repository/GameStateMockDao.java | 1 + src/test/java/repository/PieceMockDao.java | 1 + src/test/java/repository/RoomMockDao.java | 1 + src/test/java/service/ChessGameServiceTest.java | 4 ++-- src/test/java/service/GameRoomServiceTest.java | 2 +- 18 files changed, 28 insertions(+), 24 deletions(-) rename src/main/java/{db => database}/ConnectionManager.java (97%) rename src/main/java/{db => database}/JdbcTemplate.java (99%) rename src/main/java/{db => database}/RowMapper.java (90%) rename src/main/java/{repository => database/dao}/GameStateDao.java (90%) rename src/main/java/{repository => database/dao}/GameStateDaoImpl.java (94%) rename src/main/java/{repository => database/dao}/PieceDao.java (91%) rename src/main/java/{repository => database/dao}/PieceDaoImpl.java (94%) rename src/main/java/{repository => database/dao}/RoomDao.java (92%) rename src/main/java/{repository => database/dao}/RoomDaoImpl.java (96%) diff --git a/src/main/java/controller/MainController.java b/src/main/java/controller/MainController.java index d22128e9a96..d86fa6608d7 100644 --- a/src/main/java/controller/MainController.java +++ b/src/main/java/controller/MainController.java @@ -3,9 +3,9 @@ import controller.game.ChessGameController; import controller.room.GameRoomController; import dto.RoomDto; -import repository.GameStateDaoImpl; -import repository.PieceDaoImpl; -import repository.RoomDaoImpl; +import database.dao.GameStateDaoImpl; +import database.dao.PieceDaoImpl; +import database.dao.RoomDaoImpl; import service.ChessGameService; import service.GameRoomService; diff --git a/src/main/java/db/ConnectionManager.java b/src/main/java/database/ConnectionManager.java similarity index 97% rename from src/main/java/db/ConnectionManager.java rename to src/main/java/database/ConnectionManager.java index 3c4c9b83e27..a360675d0b3 100644 --- a/src/main/java/db/ConnectionManager.java +++ b/src/main/java/database/ConnectionManager.java @@ -1,4 +1,4 @@ -package db; +package database; import java.sql.Connection; import java.sql.DriverManager; diff --git a/src/main/java/db/JdbcTemplate.java b/src/main/java/database/JdbcTemplate.java similarity index 99% rename from src/main/java/db/JdbcTemplate.java rename to src/main/java/database/JdbcTemplate.java index 4225c02a3c2..1b3b106e308 100644 --- a/src/main/java/db/JdbcTemplate.java +++ b/src/main/java/database/JdbcTemplate.java @@ -1,4 +1,4 @@ -package db; +package database; import java.sql.Connection; import java.sql.PreparedStatement; diff --git a/src/main/java/db/RowMapper.java b/src/main/java/database/RowMapper.java similarity index 90% rename from src/main/java/db/RowMapper.java rename to src/main/java/database/RowMapper.java index 3d7b868fb58..bfaf494439a 100644 --- a/src/main/java/db/RowMapper.java +++ b/src/main/java/database/RowMapper.java @@ -1,4 +1,4 @@ -package db; +package database; import java.sql.ResultSet; import java.sql.SQLException; diff --git a/src/main/java/repository/GameStateDao.java b/src/main/java/database/dao/GameStateDao.java similarity index 90% rename from src/main/java/repository/GameStateDao.java rename to src/main/java/database/dao/GameStateDao.java index 91fed24e66d..af9ccf69ee7 100644 --- a/src/main/java/repository/GameStateDao.java +++ b/src/main/java/database/dao/GameStateDao.java @@ -1,4 +1,4 @@ -package repository; +package database.dao; import dto.StateDto; diff --git a/src/main/java/repository/GameStateDaoImpl.java b/src/main/java/database/dao/GameStateDaoImpl.java similarity index 94% rename from src/main/java/repository/GameStateDaoImpl.java rename to src/main/java/database/dao/GameStateDaoImpl.java index 99c89d69058..53fa226bb27 100644 --- a/src/main/java/repository/GameStateDaoImpl.java +++ b/src/main/java/database/dao/GameStateDaoImpl.java @@ -1,7 +1,7 @@ -package repository; +package database.dao; -import db.JdbcTemplate; -import db.RowMapper; +import database.JdbcTemplate; +import database.RowMapper; import dto.StateDto; import java.util.List; diff --git a/src/main/java/repository/PieceDao.java b/src/main/java/database/dao/PieceDao.java similarity index 91% rename from src/main/java/repository/PieceDao.java rename to src/main/java/database/dao/PieceDao.java index a72264bee8a..5b6444ac4d0 100644 --- a/src/main/java/repository/PieceDao.java +++ b/src/main/java/database/dao/PieceDao.java @@ -1,4 +1,4 @@ -package repository; +package database.dao; import dto.PieceDto; import dto.RoomDto; diff --git a/src/main/java/repository/PieceDaoImpl.java b/src/main/java/database/dao/PieceDaoImpl.java similarity index 94% rename from src/main/java/repository/PieceDaoImpl.java rename to src/main/java/database/dao/PieceDaoImpl.java index 634451f8e8e..015511858ca 100644 --- a/src/main/java/repository/PieceDaoImpl.java +++ b/src/main/java/database/dao/PieceDaoImpl.java @@ -1,7 +1,7 @@ -package repository; +package database.dao; -import db.JdbcTemplate; -import db.RowMapper; +import database.JdbcTemplate; +import database.RowMapper; import dto.PieceDto; import dto.RoomDto; diff --git a/src/main/java/repository/RoomDao.java b/src/main/java/database/dao/RoomDao.java similarity index 92% rename from src/main/java/repository/RoomDao.java rename to src/main/java/database/dao/RoomDao.java index 345fec26e6d..315de1f07d2 100644 --- a/src/main/java/repository/RoomDao.java +++ b/src/main/java/database/dao/RoomDao.java @@ -1,4 +1,4 @@ -package repository; +package database.dao; import dto.RoomDto; diff --git a/src/main/java/repository/RoomDaoImpl.java b/src/main/java/database/dao/RoomDaoImpl.java similarity index 96% rename from src/main/java/repository/RoomDaoImpl.java rename to src/main/java/database/dao/RoomDaoImpl.java index 105aa3dd937..46b90408a7a 100644 --- a/src/main/java/repository/RoomDaoImpl.java +++ b/src/main/java/database/dao/RoomDaoImpl.java @@ -1,7 +1,7 @@ -package repository; +package database.dao; -import db.JdbcTemplate; -import db.RowMapper; +import database.JdbcTemplate; +import database.RowMapper; import dto.RoomDto; import java.util.List; diff --git a/src/main/java/service/ChessGameService.java b/src/main/java/service/ChessGameService.java index 710cafa0291..40209b0e2f5 100644 --- a/src/main/java/service/ChessGameService.java +++ b/src/main/java/service/ChessGameService.java @@ -5,8 +5,8 @@ import dto.PieceDto; import dto.RoomDto; import dto.StateDto; -import repository.GameStateDao; -import repository.PieceDao; +import database.dao.GameStateDao; +import database.dao.PieceDao; import java.util.List; import java.util.NoSuchElementException; diff --git a/src/main/java/service/GameRoomService.java b/src/main/java/service/GameRoomService.java index 82a9ed5a177..83a152303b1 100644 --- a/src/main/java/service/GameRoomService.java +++ b/src/main/java/service/GameRoomService.java @@ -1,7 +1,7 @@ package service; import dto.RoomDto; -import repository.RoomDao; +import database.dao.RoomDao; import java.util.List; import java.util.Optional; diff --git a/src/test/java/db/ConnectionManagerTest.java b/src/test/java/db/ConnectionManagerTest.java index 4e76043447f..b554a5cadf3 100644 --- a/src/test/java/db/ConnectionManagerTest.java +++ b/src/test/java/db/ConnectionManagerTest.java @@ -1,5 +1,6 @@ package db; +import database.ConnectionManager; import org.junit.jupiter.api.Test; import java.sql.SQLException; diff --git a/src/test/java/repository/GameStateMockDao.java b/src/test/java/repository/GameStateMockDao.java index 919ecb84df6..0ca2c02f5e9 100644 --- a/src/test/java/repository/GameStateMockDao.java +++ b/src/test/java/repository/GameStateMockDao.java @@ -1,5 +1,6 @@ package repository; +import database.dao.GameStateDao; import dto.StateDto; import java.util.HashMap; diff --git a/src/test/java/repository/PieceMockDao.java b/src/test/java/repository/PieceMockDao.java index 5f3eeb9998e..4efce847254 100644 --- a/src/test/java/repository/PieceMockDao.java +++ b/src/test/java/repository/PieceMockDao.java @@ -1,5 +1,6 @@ package repository; +import database.dao.PieceDao; import dto.PieceDto; import dto.RoomDto; diff --git a/src/test/java/repository/RoomMockDao.java b/src/test/java/repository/RoomMockDao.java index e1a801945c4..beba05b300b 100644 --- a/src/test/java/repository/RoomMockDao.java +++ b/src/test/java/repository/RoomMockDao.java @@ -1,5 +1,6 @@ package repository; +import database.dao.RoomDao; import dto.RoomDto; import dto.StateDto; diff --git a/src/test/java/service/ChessGameServiceTest.java b/src/test/java/service/ChessGameServiceTest.java index 2195227015f..21b32c1a436 100644 --- a/src/test/java/service/ChessGameServiceTest.java +++ b/src/test/java/service/ChessGameServiceTest.java @@ -15,9 +15,9 @@ import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; -import repository.GameStateDao; +import database.dao.GameStateDao; import repository.GameStateMockDao; -import repository.PieceDao; +import database.dao.PieceDao; import repository.PieceMockDao; import java.util.Map; diff --git a/src/test/java/service/GameRoomServiceTest.java b/src/test/java/service/GameRoomServiceTest.java index 9accd0111ed..319cba6905e 100644 --- a/src/test/java/service/GameRoomServiceTest.java +++ b/src/test/java/service/GameRoomServiceTest.java @@ -5,7 +5,7 @@ import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; -import repository.RoomDao; +import database.dao.RoomDao; import repository.RoomMockDao; import java.util.HashMap; From f5e3c6f12cb3b8adde0807c1470dd2cacc6a9fe3 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 1 Apr 2024 16:17:45 +0900 Subject: [PATCH 78/94] =?UTF-8?q?refactor:=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/MainController.java | 4 ++-- src/main/java/controller/game/ChessGameController.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/controller/MainController.java b/src/main/java/controller/MainController.java index d86fa6608d7..25fbf3fa64c 100644 --- a/src/main/java/controller/MainController.java +++ b/src/main/java/controller/MainController.java @@ -2,10 +2,10 @@ import controller.game.ChessGameController; import controller.room.GameRoomController; -import dto.RoomDto; import database.dao.GameStateDaoImpl; import database.dao.PieceDaoImpl; import database.dao.RoomDaoImpl; +import dto.RoomDto; import service.ChessGameService; import service.GameRoomService; @@ -17,7 +17,7 @@ public class MainController { public void run() { while (true) { RoomDto roomDto = gameRoomController.run(); - chessGameController.start(roomDto); + chessGameController.run(roomDto); } } } diff --git a/src/main/java/controller/game/ChessGameController.java b/src/main/java/controller/game/ChessGameController.java index 4de15432dc2..23c8361d584 100644 --- a/src/main/java/controller/game/ChessGameController.java +++ b/src/main/java/controller/game/ChessGameController.java @@ -13,7 +13,7 @@ public ChessGameController(ChessGameService chessGameService) { this.chessGameService = chessGameService; } - public void start(RoomDto roomDto) { + public void run(RoomDto roomDto) { ChessGame chessGame = chessGameService.initializeChessGame(roomDto); OutputView.printGameGuideMessage(); while (chessGame.isPlaying()) { From 909e885f7b928adcef1a42edf8339c647cbccfd8 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 1 Apr 2024 16:44:09 +0900 Subject: [PATCH 79/94] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20Controller,=20View=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/MainController.java | 6 ++- .../java/controller/user/UserController.java | 29 +++++++++++++++ .../java/controller/user/command/Command.java | 7 ++++ .../user/command/FindUserOnDemand.java | 37 +++++++++++++++++++ src/main/java/dto/UserDto.java | 4 ++ src/main/java/view/InputView.java | 10 +++++ src/main/java/view/MessageResolver.java | 10 +++++ src/main/java/view/OutputView.java | 11 +++++- .../java/view/command/UserCommandType.java | 33 +++++++++++++++++ 9 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 src/main/java/controller/user/UserController.java create mode 100644 src/main/java/controller/user/command/Command.java create mode 100644 src/main/java/controller/user/command/FindUserOnDemand.java create mode 100644 src/main/java/dto/UserDto.java create mode 100644 src/main/java/view/command/UserCommandType.java diff --git a/src/main/java/controller/MainController.java b/src/main/java/controller/MainController.java index 25fbf3fa64c..c8d2c0964e4 100644 --- a/src/main/java/controller/MainController.java +++ b/src/main/java/controller/MainController.java @@ -2,10 +2,12 @@ import controller.game.ChessGameController; import controller.room.GameRoomController; +import controller.user.UserController; import database.dao.GameStateDaoImpl; import database.dao.PieceDaoImpl; import database.dao.RoomDaoImpl; import dto.RoomDto; +import dto.UserDto; import service.ChessGameService; import service.GameRoomService; @@ -13,10 +15,12 @@ public class MainController { private final GameRoomController gameRoomController = new GameRoomController(new GameRoomService(new RoomDaoImpl())); private final ChessGameController chessGameController = new ChessGameController(new ChessGameService( new PieceDaoImpl(), new GameStateDaoImpl())); + private final UserController userController = new UserController(new UserService(new UserDaoImpl())); public void run() { + UserDto user = userController.run(); while (true) { - RoomDto roomDto = gameRoomController.run(); + RoomDto roomDto = gameRoomController.run(user); chessGameController.run(roomDto); } } diff --git a/src/main/java/controller/user/UserController.java b/src/main/java/controller/user/UserController.java new file mode 100644 index 00000000000..4ba5dd51a6d --- /dev/null +++ b/src/main/java/controller/user/UserController.java @@ -0,0 +1,29 @@ +package controller.user; + +import dto.UserDto; +import view.InputView; +import view.OutputView; + +public class UserController { + private final UserService userService; + + public UserController(UserService userService) { + this.userService = userService; + } + + public UserDto run() { + OutputView.printUserNameInputMessage(); + UserDto user = readCommandUntilValid(); + OutputView.printUserNameMessage(user); + return user; + } + + private UserDto readCommandUntilValid() { + try { + return InputView.readUserCommand().execute(userService); + } catch (IllegalArgumentException e) { + OutputView.printErrorMessage(e); + return readCommandUntilValid(); + } + } +} diff --git a/src/main/java/controller/user/command/Command.java b/src/main/java/controller/user/command/Command.java new file mode 100644 index 00000000000..e249de7a359 --- /dev/null +++ b/src/main/java/controller/user/command/Command.java @@ -0,0 +1,7 @@ +package controller.user.command; + +import dto.UserDto; + +public interface Command { + UserDto execute(UserService userService); +} diff --git a/src/main/java/controller/user/command/FindUserOnDemand.java b/src/main/java/controller/user/command/FindUserOnDemand.java new file mode 100644 index 00000000000..0b2d752815b --- /dev/null +++ b/src/main/java/controller/user/command/FindUserOnDemand.java @@ -0,0 +1,37 @@ +package controller.user.command; + +import dto.UserDto; + +import java.util.List; + +public class FindUserOnDemand implements Command { + private static final int ARGUMENT_SIZE = 1; + + private final String username; + + public FindUserOnDemand(final List arguments) { + validateArgumentSize(arguments); + validateUsernameFormat(arguments.get(0)); + this.username = arguments.get(0); + } + + private void validateArgumentSize(final List arguments) { + if (arguments.size() != ARGUMENT_SIZE) { + throw new IllegalArgumentException(); + } + } + + private void validateUsernameFormat(final String input) { + try { + Integer.parseInt(input); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(); + } + } + + @Override + public UserDto execute(UserService userService) { + userService.findByUsername(username); + return null; + } +} diff --git a/src/main/java/dto/UserDto.java b/src/main/java/dto/UserDto.java new file mode 100644 index 00000000000..56a59dcf2d5 --- /dev/null +++ b/src/main/java/dto/UserDto.java @@ -0,0 +1,4 @@ +package dto; + +public record UserDto(String username) { +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index c075068f619..f837b91511a 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -4,6 +4,7 @@ import view.command.CommandInput; import view.command.GameCommandType; import view.command.RoomCommandType; +import view.command.UserCommandType; import java.util.List; import java.util.Scanner; @@ -30,6 +31,15 @@ public static controller.room.command.Command readRoomCommand(List room } } + public static controller.user.command.Command readUserCommand() { + try { + CommandInput input = readCommandInput(); + return UserCommandType.getCommand(input); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException(WRONG_COMMAND_ERROR_MESSAGE); + } + } + private static CommandInput readCommandInput() { return new CommandInput(SCANNER.nextLine()); } diff --git a/src/main/java/view/MessageResolver.java b/src/main/java/view/MessageResolver.java index bf6fad98c6b..a00bdebc654 100644 --- a/src/main/java/view/MessageResolver.java +++ b/src/main/java/view/MessageResolver.java @@ -8,6 +8,7 @@ import domain.position.Position; import domain.position.Rank; import dto.RoomDto; +import dto.UserDto; import java.util.Collections; import java.util.List; @@ -20,6 +21,7 @@ import static view.command.GameCommandType.START; import static view.command.RoomCommandType.NEW_ROOM; import static view.command.RoomCommandType.ROOM_SELECTION; +import static view.command.UserCommandType.FIND_USER; public class MessageResolver { private static final String LINE_SEPARATOR = System.lineSeparator(); @@ -111,4 +113,12 @@ public String resolveRoomList(final List rooms) { public String resolveEnteringRoomMessage(final RoomDto roomDto) { return roomDto.room_id() + "번 방에 입장합니다."; } + + public String resolveUserNameInputMessage() { + return String.format("> 사용자명을 입력해 주세요 : %s 사용자명 - 예 %s mangcho", FIND_USER.message(), FIND_USER.message()); + } + + public String resolveUserNameMessage(final UserDto user) { + return String.format("%s님 반갑습니다.", user.username()); + } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index e19f5555146..9857e00cef4 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -3,12 +3,13 @@ import domain.board.ChessBoard; import domain.board.Score; import dto.RoomDto; +import dto.UserDto; import java.util.List; public class OutputView { - private static final MessageResolver messageResolver = new MessageResolver(); public static final String LINE_SEPARATOR = System.lineSeparator(); + private static final MessageResolver messageResolver = new MessageResolver(); public static void printGameGuideMessage() { printWithLineSeparator(messageResolver.resolveGameStartMessage()); @@ -43,4 +44,12 @@ public static void printEnteringRoomMessage(RoomDto roomDto) { private static void printWithLineSeparator(String message) { System.out.println(message + LINE_SEPARATOR); } + + public static void printUserNameInputMessage() { + System.out.println(messageResolver.resolveUserNameInputMessage()); + } + + public static void printUserNameMessage(final UserDto user) { + System.out.println(messageResolver.resolveUserNameMessage(user)); + } } diff --git a/src/main/java/view/command/UserCommandType.java b/src/main/java/view/command/UserCommandType.java new file mode 100644 index 00000000000..fe3a0d845fd --- /dev/null +++ b/src/main/java/view/command/UserCommandType.java @@ -0,0 +1,33 @@ +package view.command; + +import controller.user.command.Command; +import controller.user.command.FindUserOnDemand; + +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; + +public enum UserCommandType { + FIND_USER("user", FindUserOnDemand::new); + + private final String command; + private final Function, Command> mapper; + + UserCommandType(final String command, final Function, Command> mapper) { + this.command = command; + this.mapper = mapper; + } + + public static Command getCommand(final CommandInput input) { + final UserCommandType commandType = Arrays.stream(UserCommandType.values()) + .filter(command -> input.prefix().equals(command.command)) + .findFirst() + .orElseThrow(IllegalArgumentException::new); + + return commandType.mapper.apply(input.getArguments()); + } + + public String message() { + return this.command; + } +} From f22f92e45fde6c239026fec8fd799f6cc95bf4a5 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 1 Apr 2024 17:07:27 +0900 Subject: [PATCH 80/94] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20Service,=20Dao=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/MainController.java | 6 ++-- .../java/controller/user/UserController.java | 1 + .../java/controller/user/command/Command.java | 1 + .../user/command/FindUserOnDemand.java | 10 +++--- src/main/java/database/dao/UserDao.java | 11 +++++++ src/main/java/database/dao/UserDaoImpl.java | 33 +++++++++++++++++++ src/main/java/service/UserService.java | 23 +++++++++++++ src/main/java/view/MessageResolver.java | 2 +- 8 files changed, 79 insertions(+), 8 deletions(-) create mode 100644 src/main/java/database/dao/UserDao.java create mode 100644 src/main/java/database/dao/UserDaoImpl.java create mode 100644 src/main/java/service/UserService.java diff --git a/src/main/java/controller/MainController.java b/src/main/java/controller/MainController.java index c8d2c0964e4..71cecd89d06 100644 --- a/src/main/java/controller/MainController.java +++ b/src/main/java/controller/MainController.java @@ -6,10 +6,12 @@ import database.dao.GameStateDaoImpl; import database.dao.PieceDaoImpl; import database.dao.RoomDaoImpl; +import database.dao.UserDaoImpl; import dto.RoomDto; import dto.UserDto; import service.ChessGameService; import service.GameRoomService; +import service.UserService; public class MainController { private final GameRoomController gameRoomController = new GameRoomController(new GameRoomService(new RoomDaoImpl())); @@ -20,8 +22,8 @@ public class MainController { public void run() { UserDto user = userController.run(); while (true) { - RoomDto roomDto = gameRoomController.run(user); - chessGameController.run(roomDto); + RoomDto room = gameRoomController.run(user); + chessGameController.run(room); } } } diff --git a/src/main/java/controller/user/UserController.java b/src/main/java/controller/user/UserController.java index 4ba5dd51a6d..beadd5ceb39 100644 --- a/src/main/java/controller/user/UserController.java +++ b/src/main/java/controller/user/UserController.java @@ -1,6 +1,7 @@ package controller.user; import dto.UserDto; +import service.UserService; import view.InputView; import view.OutputView; diff --git a/src/main/java/controller/user/command/Command.java b/src/main/java/controller/user/command/Command.java index e249de7a359..5854f5a3f31 100644 --- a/src/main/java/controller/user/command/Command.java +++ b/src/main/java/controller/user/command/Command.java @@ -1,6 +1,7 @@ package controller.user.command; import dto.UserDto; +import service.UserService; public interface Command { UserDto execute(UserService userService); diff --git a/src/main/java/controller/user/command/FindUserOnDemand.java b/src/main/java/controller/user/command/FindUserOnDemand.java index 0b2d752815b..201eeacfaca 100644 --- a/src/main/java/controller/user/command/FindUserOnDemand.java +++ b/src/main/java/controller/user/command/FindUserOnDemand.java @@ -1,11 +1,14 @@ package controller.user.command; import dto.UserDto; +import service.UserService; import java.util.List; public class FindUserOnDemand implements Command { private static final int ARGUMENT_SIZE = 1; + private static final int MINIMUM_NAME_LENGTH = 4; + private static final int MAXIMUM_NAME_LENGTH = 10; private final String username; @@ -22,16 +25,13 @@ private void validateArgumentSize(final List arguments) { } private void validateUsernameFormat(final String input) { - try { - Integer.parseInt(input); - } catch (NumberFormatException e) { + if (input.length() < MINIMUM_NAME_LENGTH || input.length() > MAXIMUM_NAME_LENGTH) { throw new IllegalArgumentException(); } } @Override public UserDto execute(UserService userService) { - userService.findByUsername(username); - return null; + return userService.findByUsername(username); } } diff --git a/src/main/java/database/dao/UserDao.java b/src/main/java/database/dao/UserDao.java new file mode 100644 index 00000000000..2dababf0aed --- /dev/null +++ b/src/main/java/database/dao/UserDao.java @@ -0,0 +1,11 @@ +package database.dao; + +import dto.UserDto; + +import java.util.Optional; + +public interface UserDao { + Optional find(String username); + + void add(String username); +} diff --git a/src/main/java/database/dao/UserDaoImpl.java b/src/main/java/database/dao/UserDaoImpl.java new file mode 100644 index 00000000000..0f8a85dcc09 --- /dev/null +++ b/src/main/java/database/dao/UserDaoImpl.java @@ -0,0 +1,33 @@ +package database.dao; + +import database.JdbcTemplate; +import database.RowMapper; +import dto.UserDto; + +import java.util.List; +import java.util.Optional; + +public class UserDaoImpl implements UserDao { + private static final String TABLE_NAME = "users"; + + private final JdbcTemplate jdbcTemplate = new JdbcTemplate(); + private final RowMapper rowMapper = (resultSet) -> new UserDto( + resultSet.getString("username") + ); + + @Override + public Optional find(final String username) { + final String query = "SELECT * FROM " + TABLE_NAME + " WHERE username = ? LIMIT 1"; + List userDtos = jdbcTemplate.executeAndGet(query, rowMapper, username); + if (userDtos.isEmpty()) { + return Optional.empty(); + } + return Optional.of(userDtos.get(0)); + } + + @Override + public void add(final String username) { + final String query = "INSERT INTO " + TABLE_NAME + " VALUES (?)"; + jdbcTemplate.execute(query, username); + } +} diff --git a/src/main/java/service/UserService.java b/src/main/java/service/UserService.java new file mode 100644 index 00000000000..9f5b4b86974 --- /dev/null +++ b/src/main/java/service/UserService.java @@ -0,0 +1,23 @@ +package service; + +import database.dao.UserDao; +import dto.UserDto; + +import java.util.Optional; + +public class UserService { + private final UserDao userDao; + + public UserService(final UserDao userDao) { + this.userDao = userDao; + } + + public UserDto findByUsername(final String username) { + Optional userDto = userDao.find(username); + if (userDto.isEmpty()) { + userDao.add(username); + userDto = userDao.find(username); + } + return userDto.orElseThrow(IllegalStateException::new); + } +} diff --git a/src/main/java/view/MessageResolver.java b/src/main/java/view/MessageResolver.java index a00bdebc654..ce94dfce387 100644 --- a/src/main/java/view/MessageResolver.java +++ b/src/main/java/view/MessageResolver.java @@ -115,7 +115,7 @@ public String resolveEnteringRoomMessage(final RoomDto roomDto) { } public String resolveUserNameInputMessage() { - return String.format("> 사용자명을 입력해 주세요 : %s 사용자명 - 예 %s mangcho", FIND_USER.message(), FIND_USER.message()); + return String.format("> 사용자명을 입력해 주세요 (4~10자) : %s 사용자명 - 예 %s mangcho", FIND_USER.message(), FIND_USER.message()); } public String resolveUserNameMessage(final UserDto user) { From 0899b82acc6924b28a1ecb19c8ece4d46a47a7ea Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Mon, 1 Apr 2024 17:50:55 +0900 Subject: [PATCH 81/94] =?UTF-8?q?feat:=20Room=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=EC=97=90=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/db/mysql/init/schema.sql | 10 +++++++- .../controller/room/GameRoomController.java | 13 +++++----- .../java/controller/room/command/Command.java | 3 ++- .../room/command/NewRoomOnCommand.java | 5 ++-- .../room/command/SelectRoomOnCommand.java | 3 ++- src/main/java/database/dao/RoomDao.java | 7 +++--- src/main/java/database/dao/RoomDaoImpl.java | 25 ++++++++----------- src/main/java/service/GameRoomService.java | 9 ++++--- src/main/java/view/OutputView.java | 12 ++++----- .../java/service/GameRoomServiceTest.java | 2 +- 10 files changed, 49 insertions(+), 40 deletions(-) diff --git a/docker/db/mysql/init/schema.sql b/docker/db/mysql/init/schema.sql index db508a6f7bd..a356fffc983 100644 --- a/docker/db/mysql/init/schema.sql +++ b/docker/db/mysql/init/schema.sql @@ -1,7 +1,15 @@ +create table users +( + username varchar(16), + primary key (username) +); + create table rooms ( + user varchar(16), room_id int, - primary key (room_id) + primary key (room_id), + foreign key (user) references users (username) ); create table game_states diff --git a/src/main/java/controller/room/GameRoomController.java b/src/main/java/controller/room/GameRoomController.java index 82fe34862db..4b43f3bbd48 100644 --- a/src/main/java/controller/room/GameRoomController.java +++ b/src/main/java/controller/room/GameRoomController.java @@ -1,6 +1,7 @@ package controller.room; import dto.RoomDto; +import dto.UserDto; import service.GameRoomService; import view.InputView; import view.OutputView; @@ -14,21 +15,21 @@ public GameRoomController(GameRoomService roomService) { this.roomService = roomService; } - public RoomDto run() { - List rooms = roomService.loadActiveRoomAll(); + public RoomDto run(UserDto user) { + List rooms = roomService.loadActiveRoomAll(user); OutputView.printGameRoomGuideMessage(rooms); - RoomDto roomDto = readCommandUntilValid(rooms); + RoomDto roomDto = readCommandUntilValid(user, rooms); OutputView.printEnteringRoomMessage(roomDto); return roomDto; } - private RoomDto readCommandUntilValid(List rooms) { + private RoomDto readCommandUntilValid(UserDto user, List rooms) { try { - return InputView.readRoomCommand(rooms).execute(roomService); + return InputView.readRoomCommand(rooms).execute(roomService, user); } catch (IllegalArgumentException e) { OutputView.printErrorMessage(e); - return readCommandUntilValid(rooms); + return readCommandUntilValid(user, rooms); } } } diff --git a/src/main/java/controller/room/command/Command.java b/src/main/java/controller/room/command/Command.java index 13ac45d0f6b..020287be95a 100644 --- a/src/main/java/controller/room/command/Command.java +++ b/src/main/java/controller/room/command/Command.java @@ -1,8 +1,9 @@ package controller.room.command; import dto.RoomDto; +import dto.UserDto; import service.GameRoomService; public interface Command { - RoomDto execute(GameRoomService gameRoomService); + RoomDto execute(GameRoomService gameRoomService, UserDto user); } diff --git a/src/main/java/controller/room/command/NewRoomOnCommand.java b/src/main/java/controller/room/command/NewRoomOnCommand.java index 5711c1bd5ff..f6f52de3078 100644 --- a/src/main/java/controller/room/command/NewRoomOnCommand.java +++ b/src/main/java/controller/room/command/NewRoomOnCommand.java @@ -1,6 +1,7 @@ package controller.room.command; import dto.RoomDto; +import dto.UserDto; import service.GameRoomService; import java.util.List; @@ -19,7 +20,7 @@ private void validateArgumentSize(final List arguments) { } @Override - public RoomDto execute(final GameRoomService gameRoomService) { - return gameRoomService.createNewRoom(); + public RoomDto execute(final GameRoomService gameRoomService, final UserDto user) { + return gameRoomService.createNewRoom(user); } } diff --git a/src/main/java/controller/room/command/SelectRoomOnCommand.java b/src/main/java/controller/room/command/SelectRoomOnCommand.java index 23cd3aa6680..b035225c546 100644 --- a/src/main/java/controller/room/command/SelectRoomOnCommand.java +++ b/src/main/java/controller/room/command/SelectRoomOnCommand.java @@ -1,6 +1,7 @@ package controller.room.command; import dto.RoomDto; +import dto.UserDto; import service.GameRoomService; import java.util.List; @@ -40,7 +41,7 @@ private void validateRoomIdRunning(final List validRooms, final String } @Override - public RoomDto execute(final GameRoomService gameRoomService) { + public RoomDto execute(final GameRoomService gameRoomService, UserDto user) { return gameRoomService.findRoomById(roomId); } } diff --git a/src/main/java/database/dao/RoomDao.java b/src/main/java/database/dao/RoomDao.java index 315de1f07d2..017ed791fd2 100644 --- a/src/main/java/database/dao/RoomDao.java +++ b/src/main/java/database/dao/RoomDao.java @@ -1,16 +1,17 @@ package database.dao; import dto.RoomDto; +import dto.UserDto; import java.util.List; import java.util.Optional; public interface RoomDao { - void add(RoomDto roomDto); + void add(UserDto userDto, RoomDto roomDto); - Optional addNewRoom(); + Optional addNewRoom(UserDto userDto); Optional find(String roomId); - List findActiveRoomAll(); + List findActiveRoomAll(final UserDto user); } diff --git a/src/main/java/database/dao/RoomDaoImpl.java b/src/main/java/database/dao/RoomDaoImpl.java index 46b90408a7a..20cf0ed1147 100644 --- a/src/main/java/database/dao/RoomDaoImpl.java +++ b/src/main/java/database/dao/RoomDaoImpl.java @@ -3,6 +3,7 @@ import database.JdbcTemplate; import database.RowMapper; import dto.RoomDto; +import dto.UserDto; import java.util.List; import java.util.Optional; @@ -16,23 +17,17 @@ public class RoomDaoImpl implements RoomDao { resultSet.getInt("room_id") ); - public void add(final RoomDto roomDto) { - final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (?)"; - jdbcTemplate.execute(insertQuery, "" + roomDto.room_id()); + public void add(final UserDto userDto, final RoomDto roomDto) { + final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (?, ?)"; + jdbcTemplate.execute(insertQuery, userDto.username(), "" + roomDto.room_id()); } - public Optional addNewRoom() { + public Optional addNewRoom(final UserDto userDto) { final String selectQuery = "SELECT MAX(room_id) AS room_id FROM " + TABLE_NAME; List roomDtos = jdbcTemplate.executeAndGet(selectQuery, rowMapper); - if (roomDtos.isEmpty()) { - final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (1)"; - int newRoomId = roomDtos.get(0).room_id() + 1; - jdbcTemplate.execute(insertQuery, String.valueOf(newRoomId)); - return Optional.of(new RoomDto(newRoomId)); - } - final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (?)"; + final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (?, ?)"; int newRoomId = roomDtos.get(0).room_id() + 1; - jdbcTemplate.execute(insertQuery, String.valueOf(newRoomId)); + jdbcTemplate.execute(insertQuery, userDto.username(), "" + newRoomId); return Optional.of(new RoomDto(newRoomId)); } @@ -45,9 +40,9 @@ public Optional find(final String roomId) { return Optional.of(roomDtos.get(0)); } - public List findActiveRoomAll() { + public List findActiveRoomAll(final UserDto user) { final String query = "SELECT * FROM " + TABLE_NAME + " AS r JOIN " - + GAME_STATUES_TABLE_NAME + " AS s ON r.room_id = s.game_id WHERE s.state != 'GAMEOVER'"; - return jdbcTemplate.executeAndGet(query, rowMapper); + + GAME_STATUES_TABLE_NAME + " AS s ON r.room_id = s.game_id WHERE r.user = ? and s.state != 'GAMEOVER'"; + return jdbcTemplate.executeAndGet(query, rowMapper, user.username()); } } diff --git a/src/main/java/service/GameRoomService.java b/src/main/java/service/GameRoomService.java index 83a152303b1..9b91ed747b2 100644 --- a/src/main/java/service/GameRoomService.java +++ b/src/main/java/service/GameRoomService.java @@ -2,6 +2,7 @@ import dto.RoomDto; import database.dao.RoomDao; +import dto.UserDto; import java.util.List; import java.util.Optional; @@ -13,12 +14,12 @@ public GameRoomService(final RoomDao roomDao) { this.roomDao = roomDao; } - public List loadActiveRoomAll() { - return roomDao.findActiveRoomAll(); + public List loadActiveRoomAll(final UserDto user) { + return roomDao.findActiveRoomAll(user); } - public RoomDto createNewRoom() { - Optional room = roomDao.addNewRoom(); + public RoomDto createNewRoom(final UserDto user) { + Optional room = roomDao.addNewRoom(user); return room.orElseThrow(IllegalStateException::new); } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index 9857e00cef4..fd14b292237 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -41,15 +41,15 @@ public static void printEnteringRoomMessage(RoomDto roomDto) { printWithLineSeparator(messageResolver.resolveEnteringRoomMessage(roomDto)); } - private static void printWithLineSeparator(String message) { - System.out.println(message + LINE_SEPARATOR); - } - public static void printUserNameInputMessage() { - System.out.println(messageResolver.resolveUserNameInputMessage()); + printWithLineSeparator(messageResolver.resolveUserNameInputMessage()); } public static void printUserNameMessage(final UserDto user) { - System.out.println(messageResolver.resolveUserNameMessage(user)); + printWithLineSeparator(messageResolver.resolveUserNameMessage(user)); + } + + private static void printWithLineSeparator(String message) { + System.out.println(LINE_SEPARATOR + message); } } diff --git a/src/test/java/service/GameRoomServiceTest.java b/src/test/java/service/GameRoomServiceTest.java index 319cba6905e..0076ca7ff0a 100644 --- a/src/test/java/service/GameRoomServiceTest.java +++ b/src/test/java/service/GameRoomServiceTest.java @@ -36,7 +36,7 @@ class GameRoomServiceTest { RoomDao roomDao = new RoomMockDao(roomRepository, turnRepository); GameRoomService gameRoomService = new GameRoomService(roomDao); - assertThat(gameRoomService.loadActiveRoomAll()) + assertThat(gameRoomService.loadActiveRoomAll(user)) .containsExactlyInAnyOrder(room2, room3); } From 7b1be6f840ab8d8d713922b85ea8d5a11823d22a Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Tue, 2 Apr 2024 00:05:05 +0900 Subject: [PATCH 82/94] =?UTF-8?q?refactor:=20=EC=9D=B8=ED=84=B0=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=20=EB=82=B4=20final=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/database/dao/RoomDao.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/database/dao/RoomDao.java b/src/main/java/database/dao/RoomDao.java index 017ed791fd2..86bcb505ba0 100644 --- a/src/main/java/database/dao/RoomDao.java +++ b/src/main/java/database/dao/RoomDao.java @@ -13,5 +13,5 @@ public interface RoomDao { Optional find(String roomId); - List findActiveRoomAll(final UserDto user); + List findActiveRoomAll(UserDto user); } From b1816b2e1324898f455fb10460d419723520a489 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Tue, 2 Apr 2024 00:24:58 +0900 Subject: [PATCH 83/94] =?UTF-8?q?fix:=20GameRoomService=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/repository/RoomMockDao.java | 43 ++++++++++--------- .../java/service/GameRoomServiceTest.java | 24 ++++++----- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/test/java/repository/RoomMockDao.java b/src/test/java/repository/RoomMockDao.java index beba05b300b..ed8747b4c03 100644 --- a/src/test/java/repository/RoomMockDao.java +++ b/src/test/java/repository/RoomMockDao.java @@ -3,47 +3,48 @@ import database.dao.RoomDao; import dto.RoomDto; import dto.StateDto; +import dto.UserDto; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; public class RoomMockDao implements RoomDao { - private final Map roomRepository; + private final Map roomRepository; private final Map turnRepository; - public RoomMockDao(Map roomRepository, Map turnRepository) { + public RoomMockDao(Map roomRepository, Map turnRepository) { this.roomRepository = roomRepository; this.turnRepository = turnRepository; } - public void add(final RoomDto roomDto) { - roomRepository.put(roomDto.room_id(), roomDto); + public void add(UserDto userDto, RoomDto roomDto) { + roomRepository.put(roomDto, userDto); } - public Optional addNewRoom() { - if (roomRepository.keySet().isEmpty()) { - RoomDto newRoomDto = new RoomDto(1); - roomRepository.put(newRoomDto.room_id(), newRoomDto); - return Optional.of(newRoomDto); - } - - int newRoomId = Collections.max(roomRepository.keySet()) + 1; - RoomDto newRoomDto = new RoomDto(newRoomId); - roomRepository.put(newRoomDto.room_id(), newRoomDto); - return Optional.of(newRoomDto); + public Optional addNewRoom(UserDto userDto) { + int newRoomId = roomRepository.keySet() + .stream() + .mapToInt(RoomDto::room_id) + .max() + .orElse(0) + 1; + RoomDto newRoom = new RoomDto(newRoomId); + roomRepository.put(newRoom, userDto); + return Optional.of(newRoom); } public Optional find(final String roomId) { - return Optional.of(roomRepository.get(Integer.parseInt(roomId))); + return roomRepository.keySet().stream() + .filter(room -> room.room_id() == Integer.parseInt(roomId)) + .findFirst(); } - public List findActiveRoomAll() { - return roomRepository.keySet().stream() - .filter(roomId -> !Objects.equals(turnRepository.get(roomId).state(), "GAMEOVER")) - .map(roomRepository::get) + public List findActiveRoomAll(final UserDto user) { + return roomRepository.entrySet().stream() + .filter(entry -> entry.getValue().equals(user)) + .filter(entry -> !Objects.equals(turnRepository.get(entry.getKey().room_id()).state(), "GAMEOVER")) + .map(Map.Entry::getKey) .toList(); } } diff --git a/src/test/java/service/GameRoomServiceTest.java b/src/test/java/service/GameRoomServiceTest.java index 0076ca7ff0a..b5d97bb5637 100644 --- a/src/test/java/service/GameRoomServiceTest.java +++ b/src/test/java/service/GameRoomServiceTest.java @@ -1,18 +1,18 @@ package service; +import database.dao.RoomDao; import dto.RoomDto; import dto.StateDto; +import dto.UserDto; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Test; -import database.dao.RoomDao; import repository.RoomMockDao; import java.util.HashMap; import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) @SuppressWarnings("NonAsciiCharacters") @@ -20,11 +20,12 @@ class GameRoomServiceTest { private final RoomDto room1 = new RoomDto(1); private final RoomDto room2 = new RoomDto(2); private final RoomDto room3 = new RoomDto(3); + private final UserDto MANGCHO = new UserDto("mangcho"); - private final Map roomRepository = Map.of( - room1.room_id(), room1, - room2.room_id(), room2, - room3.room_id(), room3); + private final Map roomRepository = Map.of( + room1, MANGCHO, + room2, MANGCHO, + room3, MANGCHO); private final Map turnRepository = Map.of( room1.room_id(), new StateDto("GAMEOVER", room1.room_id()), @@ -36,7 +37,7 @@ class GameRoomServiceTest { RoomDao roomDao = new RoomMockDao(roomRepository, turnRepository); GameRoomService gameRoomService = new GameRoomService(roomDao); - assertThat(gameRoomService.loadActiveRoomAll(user)) + assertThat(gameRoomService.loadActiveRoomAll(MANGCHO)) .containsExactlyInAnyOrder(room2, room3); } @@ -51,11 +52,12 @@ class GameRoomServiceTest { } @Test - void 새로운_방을_만든다() { - RoomDao roomDao = new RoomMockDao(new HashMap<>(), new HashMap<>()); + void 세번째_방까지_생성된_시점에_새로_생성한_방은_4번_방이다() { + RoomDao roomDao = new RoomMockDao(new HashMap<>(roomRepository), new HashMap<>()); GameRoomService gameRoomService = new GameRoomService(roomDao); - assertThatCode(gameRoomService::createNewRoom) - .doesNotThrowAnyException(); + RoomDto newRoom = gameRoomService.createNewRoom(MANGCHO); + + assertThat(newRoom).isEqualTo(new RoomDto(4)); } } From f7cb258da55c5430cc9324d8d7c6cb03a213b596 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Tue, 2 Apr 2024 14:27:51 +0900 Subject: [PATCH 84/94] =?UTF-8?q?refactor:=20final=20=ED=82=A4=EC=9B=8C?= =?UTF-8?q?=EB=93=9C=20=EC=82=AD=EC=A0=9C,=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=83=9D=EC=84=B1=EC=9E=90=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../room/command/SelectRoomOnCommand.java | 2 +- src/main/java/database/dao/PieceDaoImpl.java | 3 --- src/main/java/database/dao/RoomDaoImpl.java | 20 +++++++++++----- src/main/java/database/dao/UserDaoImpl.java | 6 ++--- src/main/java/service/ChessGameService.java | 12 +++++----- src/main/java/service/GameRoomService.java | 6 ++--- src/main/java/view/MessageResolver.java | 23 +++++++++++-------- src/main/java/view/OutputView.java | 10 ++++---- 8 files changed, 46 insertions(+), 36 deletions(-) diff --git a/src/main/java/controller/room/command/SelectRoomOnCommand.java b/src/main/java/controller/room/command/SelectRoomOnCommand.java index b035225c546..11dd17399fb 100644 --- a/src/main/java/controller/room/command/SelectRoomOnCommand.java +++ b/src/main/java/controller/room/command/SelectRoomOnCommand.java @@ -41,7 +41,7 @@ private void validateRoomIdRunning(final List validRooms, final String } @Override - public RoomDto execute(final GameRoomService gameRoomService, UserDto user) { + public RoomDto execute(final GameRoomService gameRoomService, final UserDto user) { return gameRoomService.findRoomById(roomId); } } diff --git a/src/main/java/database/dao/PieceDaoImpl.java b/src/main/java/database/dao/PieceDaoImpl.java index 015511858ca..9f09414a5b3 100644 --- a/src/main/java/database/dao/PieceDaoImpl.java +++ b/src/main/java/database/dao/PieceDaoImpl.java @@ -18,9 +18,6 @@ public class PieceDaoImpl implements PieceDao { resultSet.getString("type") ); - public PieceDaoImpl() { - } - public void add(final RoomDto room, final PieceDto piece) { final String query = "INSERT INTO " + TABLE_NAME + " VALUES(?, ?, ?, ?, ?)"; jdbcTemplate.execute(query, diff --git a/src/main/java/database/dao/RoomDaoImpl.java b/src/main/java/database/dao/RoomDaoImpl.java index 20cf0ed1147..7d1f1386c3a 100644 --- a/src/main/java/database/dao/RoomDaoImpl.java +++ b/src/main/java/database/dao/RoomDaoImpl.java @@ -23,21 +23,29 @@ public void add(final UserDto userDto, final RoomDto roomDto) { } public Optional addNewRoom(final UserDto userDto) { + final int newRoomId = getRoomIdMax() + 1; + return Optional.of(insertNewRoom(userDto, newRoomId)); + } + + private int getRoomIdMax() { final String selectQuery = "SELECT MAX(room_id) AS room_id FROM " + TABLE_NAME; - List roomDtos = jdbcTemplate.executeAndGet(selectQuery, rowMapper); + final List rooms = jdbcTemplate.executeAndGet(selectQuery, rowMapper); + return rooms.get(0).room_id(); + } + + private RoomDto insertNewRoom(final UserDto userDto, final int newRoomId) { final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (?, ?)"; - int newRoomId = roomDtos.get(0).room_id() + 1; jdbcTemplate.execute(insertQuery, userDto.username(), "" + newRoomId); - return Optional.of(new RoomDto(newRoomId)); + return new RoomDto(newRoomId); } public Optional find(final String roomId) { final String query = "SELECT * FROM " + TABLE_NAME + " WHERE room_id = ?"; - final List roomDtos = jdbcTemplate.executeAndGet(query, rowMapper, roomId); - if (roomDtos.isEmpty()) { + final List rooms = jdbcTemplate.executeAndGet(query, rowMapper, roomId); + if (rooms.isEmpty()) { return Optional.empty(); } - return Optional.of(roomDtos.get(0)); + return Optional.of(rooms.get(0)); } public List findActiveRoomAll(final UserDto user) { diff --git a/src/main/java/database/dao/UserDaoImpl.java b/src/main/java/database/dao/UserDaoImpl.java index 0f8a85dcc09..311adb0fc17 100644 --- a/src/main/java/database/dao/UserDaoImpl.java +++ b/src/main/java/database/dao/UserDaoImpl.java @@ -18,11 +18,11 @@ public class UserDaoImpl implements UserDao { @Override public Optional find(final String username) { final String query = "SELECT * FROM " + TABLE_NAME + " WHERE username = ? LIMIT 1"; - List userDtos = jdbcTemplate.executeAndGet(query, rowMapper, username); - if (userDtos.isEmpty()) { + List users = jdbcTemplate.executeAndGet(query, rowMapper, username); + if (users.isEmpty()) { return Optional.empty(); } - return Optional.of(userDtos.get(0)); + return Optional.of(users.get(0)); } @Override diff --git a/src/main/java/service/ChessGameService.java b/src/main/java/service/ChessGameService.java index 40209b0e2f5..72d275b2326 100644 --- a/src/main/java/service/ChessGameService.java +++ b/src/main/java/service/ChessGameService.java @@ -1,12 +1,12 @@ package service; +import database.dao.GameStateDao; +import database.dao.PieceDao; import domain.ChessGame; import domain.board.ChessBoardFactory; import dto.PieceDto; import dto.RoomDto; import dto.StateDto; -import database.dao.GameStateDao; -import database.dao.PieceDao; import java.util.List; import java.util.NoSuchElementException; @@ -20,9 +20,9 @@ public ChessGameService(final PieceDao pieceDao, final GameStateDao gameStateDao this.gameStateDao = gameStateDao; } - public ChessGame initializeChessGame(RoomDto roomDto) { + public ChessGame initializeChessGame(final RoomDto roomDto) { try { - StateDto stateDto = loadPreviousState(roomDto); + final StateDto stateDto = loadPreviousState(roomDto); return new ChessGame(ChessBoardFactory.loadPreviousChessBoard( loadPreviousPieces(roomDto), stateDto.getState())); } catch (NoSuchElementException e) { @@ -30,7 +30,7 @@ public ChessGame initializeChessGame(RoomDto roomDto) { } } - public void saveChessGame(ChessGame chessGame, RoomDto roomDto) { + public void saveChessGame(final ChessGame chessGame, final RoomDto roomDto) { if (chessGame.isGameOver()) { updateState(new StateDto("GAMEOVER", roomDto.room_id())); return; @@ -50,7 +50,7 @@ private StateDto loadPreviousState(final RoomDto roomDto) { private void updatePieces(final RoomDto roomDto, final List pieceDtos) { pieceDao.deleteAllByGameId(roomDto.room_id()); - for (PieceDto pieceDto : pieceDtos) { + for (final PieceDto pieceDto : pieceDtos) { pieceDao.add(roomDto, pieceDto); } } diff --git a/src/main/java/service/GameRoomService.java b/src/main/java/service/GameRoomService.java index 9b91ed747b2..6dda5c16e62 100644 --- a/src/main/java/service/GameRoomService.java +++ b/src/main/java/service/GameRoomService.java @@ -1,7 +1,7 @@ package service; -import dto.RoomDto; import database.dao.RoomDao; +import dto.RoomDto; import dto.UserDto; import java.util.List; @@ -19,12 +19,12 @@ public List loadActiveRoomAll(final UserDto user) { } public RoomDto createNewRoom(final UserDto user) { - Optional room = roomDao.addNewRoom(user); + final Optional room = roomDao.addNewRoom(user); return room.orElseThrow(IllegalStateException::new); } public RoomDto findRoomById(final String roomId) { - Optional room = roomDao.find(roomId); + final Optional room = roomDao.find(roomId); return room.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 방입니다.")); } } diff --git a/src/main/java/view/MessageResolver.java b/src/main/java/view/MessageResolver.java index ce94dfce387..a7ca6c97760 100644 --- a/src/main/java/view/MessageResolver.java +++ b/src/main/java/view/MessageResolver.java @@ -45,7 +45,7 @@ public String resolveGameStartMessage() { gameEndCommandMessage, gameMoveCommandMessage); } - public String resolveBoard(ChessBoard board) { + public String resolveBoardMessage(ChessBoard board) { List boardMessage = IntStream.rangeClosed(1, 8) .mapToObj(rank -> resolveOneRank(board, Rank.fromNumber(rank))) .collect(Collectors.toList()); @@ -84,41 +84,46 @@ private String pieceDisplay(Piece piece) { return pieceName; } - public String resolveScore(Score score) { + public String resolveScoreMessage(Score score) { String whiteScoreMessage = String.format("WHITE 점수: %.1f", score.getWhiteScore()); String blackScoreMessage = String.format("BLACK 점수: %.1f", score.getBlackScore()); return String.join(LINE_SEPARATOR, whiteScoreMessage, blackScoreMessage); } - public String resolveWinner(final Score score) { + public String resolveWinnerMessage(Score score) { if (score.getWhiteScore() > score.getBlackScore()) { return "우승자는 WHITE입니다!"; } return "우승자는 BLACK입니다!"; } - public String resolveRoomList(final List rooms) { + public String resolveRoomGuideMessage(List rooms) { String newRoomMessage = String.format("> 새로운 방 생성 : %s", NEW_ROOM.message()); if (rooms.isEmpty()) { return newRoomMessage; } + return String.join(LINE_SEPARATOR, newRoomMessage, resolveRooms(rooms)); + } - String roomGuideHeaderMessage = String.format("> 입장할 방 선택 : %s 방번호 - 예 %s 1", ROOM_SELECTION.message(), ROOM_SELECTION.message()); + private String resolveRooms(List rooms) { + String roomGuideHeaderMessage = String.format("> 입장할 방 선택 : %s 방번호 - 예 %s 1", + ROOM_SELECTION.message(), ROOM_SELECTION.message()); String roomListMessage = "> 방 목록 : " + rooms.stream() .map(room -> String.valueOf(room.room_id())) .collect(Collectors.joining(", ")); - return String.join(LINE_SEPARATOR, newRoomMessage, roomGuideHeaderMessage, roomListMessage); + return String.join(LINE_SEPARATOR, roomGuideHeaderMessage, roomListMessage); } - public String resolveEnteringRoomMessage(final RoomDto roomDto) { + public String resolveEnteringRoomMessage(RoomDto roomDto) { return roomDto.room_id() + "번 방에 입장합니다."; } public String resolveUserNameInputMessage() { - return String.format("> 사용자명을 입력해 주세요 (4~10자) : %s 사용자명 - 예 %s mangcho", FIND_USER.message(), FIND_USER.message()); + return String.format("> 사용자명을 입력해 주세요 (4~10자) : %s 사용자명 - 예 %s mangcho", + FIND_USER.message(), FIND_USER.message()); } - public String resolveUserNameMessage(final UserDto user) { + public String resolveUserNameMessage(UserDto user) { return String.format("%s님 반갑습니다.", user.username()); } } diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java index fd14b292237..4bda2c9d400 100644 --- a/src/main/java/view/OutputView.java +++ b/src/main/java/view/OutputView.java @@ -16,17 +16,17 @@ public static void printGameGuideMessage() { } public static void printBoard(ChessBoard board) { - String boardMessage = messageResolver.resolveBoard(board); + String boardMessage = messageResolver.resolveBoardMessage(board); printWithLineSeparator(boardMessage); } public static void printScore(Score score) { - String scoreMessage = messageResolver.resolveScore(score); + String scoreMessage = messageResolver.resolveScoreMessage(score); printWithLineSeparator(scoreMessage); } public static void printWinner(Score score) { - printWithLineSeparator(messageResolver.resolveWinner(score)); + printWithLineSeparator(messageResolver.resolveWinnerMessage(score)); } public static void printErrorMessage(Exception e) { @@ -34,7 +34,7 @@ public static void printErrorMessage(Exception e) { } public static void printGameRoomGuideMessage(List rooms) { - printWithLineSeparator(messageResolver.resolveRoomList(rooms)); + printWithLineSeparator(messageResolver.resolveRoomGuideMessage(rooms)); } public static void printEnteringRoomMessage(RoomDto roomDto) { @@ -45,7 +45,7 @@ public static void printUserNameInputMessage() { printWithLineSeparator(messageResolver.resolveUserNameInputMessage()); } - public static void printUserNameMessage(final UserDto user) { + public static void printUserNameMessage(UserDto user) { printWithLineSeparator(messageResolver.resolveUserNameMessage(user)); } From 2871ed4ae2feb87ab11fd63ad8b45709da332e1d Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Tue, 2 Apr 2024 15:30:38 +0900 Subject: [PATCH 85/94] =?UTF-8?q?fix:=20=EA=B3=B5=EB=B0=B1=EC=9D=B4=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=EB=90=98=EB=A9=B4=20null=EC=9D=B4=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D=ED=95=98=EB=8A=94=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/InputView.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index f837b91511a..1ecc48977cf 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -7,6 +7,7 @@ import view.command.UserCommandType; import java.util.List; +import java.util.NoSuchElementException; import java.util.Scanner; public class InputView { @@ -26,7 +27,7 @@ public static controller.room.command.Command readRoomCommand(List room try { CommandInput input = readCommandInput(); return RoomCommandType.getCommand(input, rooms); - } catch (IllegalArgumentException e) { + } catch (IllegalArgumentException | NoSuchElementException e) { throw new IllegalArgumentException(WRONG_COMMAND_ERROR_MESSAGE); } } @@ -35,12 +36,12 @@ public static controller.user.command.Command readUserCommand() { try { CommandInput input = readCommandInput(); return UserCommandType.getCommand(input); - } catch (IllegalArgumentException e) { + } catch (IllegalArgumentException | NoSuchElementException e) { throw new IllegalArgumentException(WRONG_COMMAND_ERROR_MESSAGE); } } private static CommandInput readCommandInput() { - return new CommandInput(SCANNER.nextLine()); + return new CommandInput(SCANNER.nextLine().strip()); } } From 87697082d41068ee2ce535d1246dbbb3038d07c0 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Wed, 3 Apr 2024 22:06:05 +0900 Subject: [PATCH 86/94] =?UTF-8?q?docs:=20=EC=B6=94=EA=B0=80=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A52=EC=99=80=20=EA=B4=80=EB=A0=A8=EB=90=9C=20=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index fc5e2cde7c2..c8d1d264f7b 100644 --- a/README.md +++ b/README.md @@ -144,13 +144,22 @@ ### 추가 기능 1: 체스 게임방을 만들고 체스 게임방에 입장할 수 있는 기능을 추가한다. -- [ ] 존재하는 모든 게임방 번호를 조회한다. - - [ ] 종료된 게임은 제외한다. -- [ ] 입장할 게임방 번호를 입력 받는다. - - [ ] new를 입력하면 새로운 방을 생성한다. - - **[예외]** 종료된 게임방 번호 - - **[예외]** 존재하지 않는 게임방 번호 -- [ ] 게임을 생성한다. (턴, 피스들) - - [ ] 기존 데이터를 불러오기 - - [ ] 새로 생성하기 -- [ ] end를 입력하면 게임 데이터를 저장한다. +- [x] 존재하는 모든 게임방 번호를 조회한다. + - [x] 종료된 게임은 제외한다. +- [x] 입장할 게임방 번호를 입력 받는다. + - [x] new를 입력하면 새로운 방을 생성한다. + - **[예외]** 종료된 게임방 번호 + - **[예외]** 존재하지 않는 게임방 번호 +- [x] 게임을 생성한다. (턴, 피스들) + - [x] 기존 데이터를 불러오기 + - [x] 새로 생성하기 +- [x] end를 입력하면 게임 데이터를 저장한다. + +### 추가 기능 2: 사용자별로 체스 게임 기록을 관리할 수 있다. + +- [x] 사용자 이름을 입력 받는다. + - **[예외]** 사용자 이름은 4~10자 사이여야 한다. +- [x] DB에서 사용자 정보를 불러온다. + - [x] 존재하지 않는 사용자라면 새로 추가한다. +- [x] 사용자의 게임 기록을 불러온다. +- 이후는 기존 어플리케이션 흐름대로 진행 From e36ef5c1f2445859290d84d850575c0e48575c0e Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Wed, 3 Apr 2024 22:12:44 +0900 Subject: [PATCH 87/94] =?UTF-8?q?refactor:=20Command=20=EC=9D=B8=ED=84=B0?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=8A=A4=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ndOnCommand.java => EndOnGameCommand.java} | 4 ++-- .../{Command.java => GameCommand.java} | 2 +- ...eOnCommand.java => MoveOnGameCommand.java} | 4 ++-- ...OnCommand.java => StartOnGameCommand.java} | 4 ++-- ...nCommand.java => StatusOnGameCommand.java} | 4 ++-- ...Command.java => NewRoomOnRoomCommand.java} | 4 ++-- .../{Command.java => RoomCommand.java} | 2 +- ...mand.java => SelectRoomOnRoomCommand.java} | 4 ++-- .../user/command/FindUserOnDemand.java | 2 +- .../{Command.java => UserCommand.java} | 2 +- src/main/java/view/InputView.java | 9 ++++--- .../java/view/command/GameCommandType.java | 24 +++++++++---------- .../java/view/command/RoomCommandType.java | 16 ++++++------- .../java/view/command/UserCommandType.java | 8 +++---- 14 files changed, 46 insertions(+), 43 deletions(-) rename src/main/java/controller/game/command/{EndOnCommand.java => EndOnGameCommand.java} (79%) rename src/main/java/controller/game/command/{Command.java => GameCommand.java} (75%) rename src/main/java/controller/game/command/{MoveOnCommand.java => MoveOnGameCommand.java} (92%) rename src/main/java/controller/game/command/{StartOnCommand.java => StartOnGameCommand.java} (81%) rename src/main/java/controller/game/command/{StatusOnCommand.java => StatusOnGameCommand.java} (82%) rename src/main/java/controller/room/command/{NewRoomOnCommand.java => NewRoomOnRoomCommand.java} (82%) rename src/main/java/controller/room/command/{Command.java => RoomCommand.java} (85%) rename src/main/java/controller/room/command/{SelectRoomOnCommand.java => SelectRoomOnRoomCommand.java} (89%) rename src/main/java/controller/user/command/{Command.java => UserCommand.java} (80%) diff --git a/src/main/java/controller/game/command/EndOnCommand.java b/src/main/java/controller/game/command/EndOnGameCommand.java similarity index 79% rename from src/main/java/controller/game/command/EndOnCommand.java rename to src/main/java/controller/game/command/EndOnGameCommand.java index 885d147eddc..ef7883fba92 100644 --- a/src/main/java/controller/game/command/EndOnCommand.java +++ b/src/main/java/controller/game/command/EndOnGameCommand.java @@ -4,10 +4,10 @@ import java.util.List; -public class EndOnCommand implements Command { +public class EndOnGameCommand implements GameCommand { private static final int ARGUMENT_SIZE = 0; - public EndOnCommand(final List arguments) { + public EndOnGameCommand(final List arguments) { validateArgumentSize(arguments); } diff --git a/src/main/java/controller/game/command/Command.java b/src/main/java/controller/game/command/GameCommand.java similarity index 75% rename from src/main/java/controller/game/command/Command.java rename to src/main/java/controller/game/command/GameCommand.java index 5a537fc7762..3139a3cc479 100644 --- a/src/main/java/controller/game/command/Command.java +++ b/src/main/java/controller/game/command/GameCommand.java @@ -2,6 +2,6 @@ import domain.ChessGame; -public interface Command { +public interface GameCommand { void execute(ChessGame game); } diff --git a/src/main/java/controller/game/command/MoveOnCommand.java b/src/main/java/controller/game/command/MoveOnGameCommand.java similarity index 92% rename from src/main/java/controller/game/command/MoveOnCommand.java rename to src/main/java/controller/game/command/MoveOnGameCommand.java index 3398e44046d..ec7630be1e0 100644 --- a/src/main/java/controller/game/command/MoveOnCommand.java +++ b/src/main/java/controller/game/command/MoveOnGameCommand.java @@ -8,14 +8,14 @@ import java.util.List; import java.util.regex.Pattern; -public class MoveOnCommand implements Command { +public class MoveOnGameCommand implements GameCommand { private static final Pattern POSITION_INPUT_PATTERN = Pattern.compile("^[A-H][1-8]$"); private static final int ARGUMENT_SIZE = 2; private final Position source; private final Position target; - public MoveOnCommand(final List arguments) { + public MoveOnGameCommand(final List arguments) { validateArgumentSize(arguments); this.source = new Position(arguments.get(0)); this.target = new Position(arguments.get(1)); diff --git a/src/main/java/controller/game/command/StartOnCommand.java b/src/main/java/controller/game/command/StartOnGameCommand.java similarity index 81% rename from src/main/java/controller/game/command/StartOnCommand.java rename to src/main/java/controller/game/command/StartOnGameCommand.java index a3598e6802d..dd619c1da78 100644 --- a/src/main/java/controller/game/command/StartOnCommand.java +++ b/src/main/java/controller/game/command/StartOnGameCommand.java @@ -5,10 +5,10 @@ import java.util.List; -public class StartOnCommand implements Command { +public class StartOnGameCommand implements GameCommand { private static final int ARGUMENT_SIZE = 0; - public StartOnCommand(final List arguments) { + public StartOnGameCommand(final List arguments) { validateArgumentSize(arguments); } diff --git a/src/main/java/controller/game/command/StatusOnCommand.java b/src/main/java/controller/game/command/StatusOnGameCommand.java similarity index 82% rename from src/main/java/controller/game/command/StatusOnCommand.java rename to src/main/java/controller/game/command/StatusOnGameCommand.java index 42bdeba5258..4be90a202b9 100644 --- a/src/main/java/controller/game/command/StatusOnCommand.java +++ b/src/main/java/controller/game/command/StatusOnGameCommand.java @@ -6,10 +6,10 @@ import java.util.List; -public class StatusOnCommand implements Command { +public class StatusOnGameCommand implements GameCommand { private static final int ARGUMENT_SIZE = 0; - public StatusOnCommand(final List arguments) { + public StatusOnGameCommand(final List arguments) { validateArgumentSize(arguments); } diff --git a/src/main/java/controller/room/command/NewRoomOnCommand.java b/src/main/java/controller/room/command/NewRoomOnRoomCommand.java similarity index 82% rename from src/main/java/controller/room/command/NewRoomOnCommand.java rename to src/main/java/controller/room/command/NewRoomOnRoomCommand.java index f6f52de3078..fb9abfb7e51 100644 --- a/src/main/java/controller/room/command/NewRoomOnCommand.java +++ b/src/main/java/controller/room/command/NewRoomOnRoomCommand.java @@ -6,10 +6,10 @@ import java.util.List; -public class NewRoomOnCommand implements Command { +public class NewRoomOnRoomCommand implements RoomCommand { private static final int ARGUMENT_SIZE = 0; - public NewRoomOnCommand(final List arguments) { + public NewRoomOnRoomCommand(final List arguments) { validateArgumentSize(arguments); } diff --git a/src/main/java/controller/room/command/Command.java b/src/main/java/controller/room/command/RoomCommand.java similarity index 85% rename from src/main/java/controller/room/command/Command.java rename to src/main/java/controller/room/command/RoomCommand.java index 020287be95a..d6aed0280ad 100644 --- a/src/main/java/controller/room/command/Command.java +++ b/src/main/java/controller/room/command/RoomCommand.java @@ -4,6 +4,6 @@ import dto.UserDto; import service.GameRoomService; -public interface Command { +public interface RoomCommand { RoomDto execute(GameRoomService gameRoomService, UserDto user); } diff --git a/src/main/java/controller/room/command/SelectRoomOnCommand.java b/src/main/java/controller/room/command/SelectRoomOnRoomCommand.java similarity index 89% rename from src/main/java/controller/room/command/SelectRoomOnCommand.java rename to src/main/java/controller/room/command/SelectRoomOnRoomCommand.java index 11dd17399fb..56122ff3661 100644 --- a/src/main/java/controller/room/command/SelectRoomOnCommand.java +++ b/src/main/java/controller/room/command/SelectRoomOnRoomCommand.java @@ -6,12 +6,12 @@ import java.util.List; -public class SelectRoomOnCommand implements Command { +public class SelectRoomOnRoomCommand implements RoomCommand { private static final int ARGUMENT_SIZE = 1; private final String roomId; - public SelectRoomOnCommand(final List arguments, final List validRooms) { + public SelectRoomOnRoomCommand(final List arguments, final List validRooms) { validateArgumentSize(arguments); validateRoomIdFormat(arguments.get(0)); validateRoomIdRunning(validRooms, arguments.get(0)); diff --git a/src/main/java/controller/user/command/FindUserOnDemand.java b/src/main/java/controller/user/command/FindUserOnDemand.java index 201eeacfaca..1a82a0e8765 100644 --- a/src/main/java/controller/user/command/FindUserOnDemand.java +++ b/src/main/java/controller/user/command/FindUserOnDemand.java @@ -5,7 +5,7 @@ import java.util.List; -public class FindUserOnDemand implements Command { +public class FindUserOnDemand implements UserCommand { private static final int ARGUMENT_SIZE = 1; private static final int MINIMUM_NAME_LENGTH = 4; private static final int MAXIMUM_NAME_LENGTH = 10; diff --git a/src/main/java/controller/user/command/Command.java b/src/main/java/controller/user/command/UserCommand.java similarity index 80% rename from src/main/java/controller/user/command/Command.java rename to src/main/java/controller/user/command/UserCommand.java index 5854f5a3f31..c5418dfff7e 100644 --- a/src/main/java/controller/user/command/Command.java +++ b/src/main/java/controller/user/command/UserCommand.java @@ -3,6 +3,6 @@ import dto.UserDto; import service.UserService; -public interface Command { +public interface UserCommand { UserDto execute(UserService userService); } diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java index 1ecc48977cf..dba766294a5 100644 --- a/src/main/java/view/InputView.java +++ b/src/main/java/view/InputView.java @@ -1,5 +1,8 @@ package view; +import controller.game.command.GameCommand; +import controller.room.command.RoomCommand; +import controller.user.command.UserCommand; import dto.RoomDto; import view.command.CommandInput; import view.command.GameCommandType; @@ -14,7 +17,7 @@ public class InputView { private static final Scanner SCANNER = new Scanner(System.in); private static final String WRONG_COMMAND_ERROR_MESSAGE = "잘못된 명령어입니다."; - public static controller.game.command.Command readGameCommand() { + public static GameCommand readGameCommand() { try { CommandInput input = readCommandInput(); return GameCommandType.getCommand(input); @@ -23,7 +26,7 @@ public static controller.game.command.Command readGameCommand() { } } - public static controller.room.command.Command readRoomCommand(List rooms) { + public static RoomCommand readRoomCommand(List rooms) { try { CommandInput input = readCommandInput(); return RoomCommandType.getCommand(input, rooms); @@ -32,7 +35,7 @@ public static controller.room.command.Command readRoomCommand(List room } } - public static controller.user.command.Command readUserCommand() { + public static UserCommand readUserCommand() { try { CommandInput input = readCommandInput(); return UserCommandType.getCommand(input); diff --git a/src/main/java/view/command/GameCommandType.java b/src/main/java/view/command/GameCommandType.java index dbbac9a6f30..1df65db739b 100644 --- a/src/main/java/view/command/GameCommandType.java +++ b/src/main/java/view/command/GameCommandType.java @@ -1,30 +1,30 @@ package view.command; -import controller.game.command.Command; -import controller.game.command.EndOnCommand; -import controller.game.command.MoveOnCommand; -import controller.game.command.StartOnCommand; -import controller.game.command.StatusOnCommand; +import controller.game.command.GameCommand; +import controller.game.command.EndOnGameCommand; +import controller.game.command.MoveOnGameCommand; +import controller.game.command.StartOnGameCommand; +import controller.game.command.StatusOnGameCommand; import java.util.Arrays; import java.util.List; import java.util.function.Function; public enum GameCommandType { - START("start", StartOnCommand::new), - END("end", EndOnCommand::new), - STATUS("status", StatusOnCommand::new), - MOVE("move", MoveOnCommand::new); + START("start", StartOnGameCommand::new), + END("end", EndOnGameCommand::new), + STATUS("status", StatusOnGameCommand::new), + MOVE("move", MoveOnGameCommand::new); private final String command; - private final Function, Command> mapper; + private final Function, GameCommand> mapper; - GameCommandType(final String command, final Function, Command> mapper) { + GameCommandType(final String command, final Function, GameCommand> mapper) { this.command = command; this.mapper = mapper; } - public static Command getCommand(final CommandInput input) { + public static GameCommand getCommand(final CommandInput input) { final GameCommandType commandType = Arrays.stream(GameCommandType.values()) .filter(command -> input.prefix().equals(command.command)) .findFirst() diff --git a/src/main/java/view/command/RoomCommandType.java b/src/main/java/view/command/RoomCommandType.java index 30a52b7a9ff..fb0a63b5f2a 100644 --- a/src/main/java/view/command/RoomCommandType.java +++ b/src/main/java/view/command/RoomCommandType.java @@ -1,8 +1,8 @@ package view.command; -import controller.room.command.Command; -import controller.room.command.NewRoomOnCommand; -import controller.room.command.SelectRoomOnCommand; +import controller.room.command.RoomCommand; +import controller.room.command.NewRoomOnRoomCommand; +import controller.room.command.SelectRoomOnRoomCommand; import dto.RoomDto; import java.util.Arrays; @@ -10,18 +10,18 @@ import java.util.function.BiFunction; public enum RoomCommandType { - NEW_ROOM("new", (arguments, rooms) -> new NewRoomOnCommand(arguments)), - ROOM_SELECTION("room", SelectRoomOnCommand::new); + NEW_ROOM("new", (arguments, rooms) -> new NewRoomOnRoomCommand(arguments)), + ROOM_SELECTION("room", SelectRoomOnRoomCommand::new); private final String command; - private final BiFunction, List, Command> mapper; + private final BiFunction, List, RoomCommand> mapper; - RoomCommandType(final String command, final BiFunction, List, Command> mapper) { + RoomCommandType(final String command, final BiFunction, List, RoomCommand> mapper) { this.command = command; this.mapper = mapper; } - public static Command getCommand(final CommandInput input, final List rooms) { + public static RoomCommand getCommand(final CommandInput input, final List rooms) { final RoomCommandType commandType = Arrays.stream(RoomCommandType.values()) .filter(command -> input.prefix().equals(command.command)) .findFirst() diff --git a/src/main/java/view/command/UserCommandType.java b/src/main/java/view/command/UserCommandType.java index fe3a0d845fd..300fca66a10 100644 --- a/src/main/java/view/command/UserCommandType.java +++ b/src/main/java/view/command/UserCommandType.java @@ -1,6 +1,6 @@ package view.command; -import controller.user.command.Command; +import controller.user.command.UserCommand; import controller.user.command.FindUserOnDemand; import java.util.Arrays; @@ -11,14 +11,14 @@ public enum UserCommandType { FIND_USER("user", FindUserOnDemand::new); private final String command; - private final Function, Command> mapper; + private final Function, UserCommand> mapper; - UserCommandType(final String command, final Function, Command> mapper) { + UserCommandType(final String command, final Function, UserCommand> mapper) { this.command = command; this.mapper = mapper; } - public static Command getCommand(final CommandInput input) { + public static UserCommand getCommand(final CommandInput input) { final UserCommandType commandType = Arrays.stream(UserCommandType.values()) .filter(command -> input.prefix().equals(command.command)) .findFirst() From c885bed933e3d0fd76e1bd158eeb5c12f0544426 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Wed, 3 Apr 2024 22:28:40 +0900 Subject: [PATCH 88/94] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EA=B4=84=ED=98=B8,=20=EA=B0=9C=ED=96=89=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C,=20final=20=ED=82=A4=EC=9B=8C=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/database/dao/GameStateDaoImpl.java | 2 +- src/main/java/database/dao/PieceDaoImpl.java | 4 ++-- src/main/java/database/dao/RoomDaoImpl.java | 6 +++--- src/main/java/database/dao/UserDaoImpl.java | 2 +- .../java/domain/board/ChessBoardFactory.java | 19 +++++++++---------- src/main/java/domain/board/Score.java | 4 ++-- src/main/java/service/GameRoomService.java | 4 ++-- 7 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/main/java/database/dao/GameStateDaoImpl.java b/src/main/java/database/dao/GameStateDaoImpl.java index 53fa226bb27..0efe6fe2ac0 100644 --- a/src/main/java/database/dao/GameStateDaoImpl.java +++ b/src/main/java/database/dao/GameStateDaoImpl.java @@ -11,7 +11,7 @@ public class GameStateDaoImpl implements GameStateDao { private static final String TABLE_NAME = "game_states"; private final JdbcTemplate jdbcTemplate = new JdbcTemplate(); - private final RowMapper rowMapper = (resultSet) -> new StateDto( + private final RowMapper rowMapper = resultSet -> new StateDto( resultSet.getString("state"), resultSet.getInt("game_id") ); diff --git a/src/main/java/database/dao/PieceDaoImpl.java b/src/main/java/database/dao/PieceDaoImpl.java index 9f09414a5b3..145883b43df 100644 --- a/src/main/java/database/dao/PieceDaoImpl.java +++ b/src/main/java/database/dao/PieceDaoImpl.java @@ -11,7 +11,7 @@ public class PieceDaoImpl implements PieceDao { private static final String TABLE_NAME = "pieces"; private final JdbcTemplate jdbcTemplate = new JdbcTemplate(); - private final RowMapper rowMapper = (resultSet) -> new PieceDto( + private final RowMapper rowMapper = resultSet -> new PieceDto( resultSet.getString("board_file"), resultSet.getString("board_rank"), resultSet.getString("color"), @@ -21,7 +21,7 @@ public class PieceDaoImpl implements PieceDao { public void add(final RoomDto room, final PieceDto piece) { final String query = "INSERT INTO " + TABLE_NAME + " VALUES(?, ?, ?, ?, ?)"; jdbcTemplate.execute(query, - String.valueOf(room.room_id()), piece.boardFile(), piece.boardRank(), + String.valueOf(room.roomId()), piece.boardFile(), piece.boardRank(), piece.color(), piece.type()); } diff --git a/src/main/java/database/dao/RoomDaoImpl.java b/src/main/java/database/dao/RoomDaoImpl.java index 7d1f1386c3a..c305d15b080 100644 --- a/src/main/java/database/dao/RoomDaoImpl.java +++ b/src/main/java/database/dao/RoomDaoImpl.java @@ -13,13 +13,13 @@ public class RoomDaoImpl implements RoomDao { private static final String GAME_STATUES_TABLE_NAME = "game_states"; private final JdbcTemplate jdbcTemplate = new JdbcTemplate(); - private final RowMapper rowMapper = (resultSet) -> new RoomDto( + private final RowMapper rowMapper = resultSet -> new RoomDto( resultSet.getInt("room_id") ); public void add(final UserDto userDto, final RoomDto roomDto) { final String insertQuery = "INSERT INTO " + TABLE_NAME + " VALUES (?, ?)"; - jdbcTemplate.execute(insertQuery, userDto.username(), "" + roomDto.room_id()); + jdbcTemplate.execute(insertQuery, userDto.username(), "" + roomDto.roomId()); } public Optional addNewRoom(final UserDto userDto) { @@ -30,7 +30,7 @@ public Optional addNewRoom(final UserDto userDto) { private int getRoomIdMax() { final String selectQuery = "SELECT MAX(room_id) AS room_id FROM " + TABLE_NAME; final List rooms = jdbcTemplate.executeAndGet(selectQuery, rowMapper); - return rooms.get(0).room_id(); + return rooms.get(0).roomId(); } private RoomDto insertNewRoom(final UserDto userDto, final int newRoomId) { diff --git a/src/main/java/database/dao/UserDaoImpl.java b/src/main/java/database/dao/UserDaoImpl.java index 311adb0fc17..2ac14c6cd1d 100644 --- a/src/main/java/database/dao/UserDaoImpl.java +++ b/src/main/java/database/dao/UserDaoImpl.java @@ -11,7 +11,7 @@ public class UserDaoImpl implements UserDao { private static final String TABLE_NAME = "users"; private final JdbcTemplate jdbcTemplate = new JdbcTemplate(); - private final RowMapper rowMapper = (resultSet) -> new UserDto( + private final RowMapper rowMapper = resultSet -> new UserDto( resultSet.getString("username") ); diff --git a/src/main/java/domain/board/ChessBoardFactory.java b/src/main/java/domain/board/ChessBoardFactory.java index 70846bd42b6..94d349cae60 100644 --- a/src/main/java/domain/board/ChessBoardFactory.java +++ b/src/main/java/domain/board/ChessBoardFactory.java @@ -1,6 +1,5 @@ package domain.board; -import dto.PieceDto; import domain.piece.Color; import domain.piece.Piece; import domain.piece.nonpawn.Bishop; @@ -13,6 +12,7 @@ import domain.position.File; import domain.position.Position; import domain.position.Rank; +import dto.PieceDto; import java.util.HashMap; import java.util.List; @@ -30,9 +30,6 @@ public class ChessBoardFactory { new King(Color.BLACK), new Bishop(Color.BLACK), new Knight(Color.BLACK), new Rook(Color.BLACK) ); - private ChessBoardFactory() { - } - public static ChessBoard createInitialChessBoard() { final Map pieceMap = new HashMap<>(); for (int order = 0; order < SPECIAL_PIECE_SIZE; order++) { @@ -44,11 +41,13 @@ public static ChessBoard createInitialChessBoard() { return new ChessBoard(pieceMap); } - public static ChessBoard loadPreviousChessBoard(List pieceDtos, final Color turn) { - return pieceDtos.stream() - .collect(Collectors.collectingAndThen(Collectors.toMap( - PieceDto::getPosition, - PieceDto::getPiece - ), board -> new ChessBoard(board, turn))); + public static ChessBoard loadPreviousChessBoard(final List pieces, final Color turn) { + return pieces.stream() + .collect( + Collectors.collectingAndThen( + Collectors.toMap(PieceDto::getPosition, PieceDto::getPiece), + board -> new ChessBoard(board, turn) + ) + ); } } diff --git a/src/main/java/domain/board/Score.java b/src/main/java/domain/board/Score.java index 50ded9dd063..37fbdca3dd2 100644 --- a/src/main/java/domain/board/Score.java +++ b/src/main/java/domain/board/Score.java @@ -20,8 +20,8 @@ private Score(final double whiteScore, final double blackScore) { } public static Score calculate(final Map board) { - double whiteScore = calculateBoardScore(board, Color.WHITE); - double blackScore = calculateBoardScore(board, Color.BLACK); + final double whiteScore = calculateBoardScore(board, Color.WHITE); + final double blackScore = calculateBoardScore(board, Color.BLACK); return new Score(whiteScore, blackScore); } diff --git a/src/main/java/service/GameRoomService.java b/src/main/java/service/GameRoomService.java index 6dda5c16e62..0f989f5eaca 100644 --- a/src/main/java/service/GameRoomService.java +++ b/src/main/java/service/GameRoomService.java @@ -24,7 +24,7 @@ public RoomDto createNewRoom(final UserDto user) { } public RoomDto findRoomById(final String roomId) { - final Optional room = roomDao.find(roomId); - return room.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 방입니다.")); + return roomDao.find(roomId) + .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 방입니다.")); } } From f21dd5bb3bdb8fc7957c755eefd81580113fc9af Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Wed, 3 Apr 2024 22:29:19 +0900 Subject: [PATCH 89/94] =?UTF-8?q?refactor:=20roomId=20=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=20=EB=B3=80=EC=88=98=EB=AA=85=EA=B3=BC=20=EC=BF=BC=EB=A6=AC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/MainController.java | 9 +++++++-- .../room/command/SelectRoomOnRoomCommand.java | 2 +- src/main/java/dto/RoomDto.java | 2 +- src/main/java/service/ChessGameService.java | 10 +++++----- src/main/java/view/MessageResolver.java | 4 ++-- src/test/java/repository/PieceMockDao.java | 2 +- src/test/java/repository/RoomMockDao.java | 6 +++--- src/test/java/service/GameRoomServiceTest.java | 6 +++--- 8 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/main/java/controller/MainController.java b/src/main/java/controller/MainController.java index 71cecd89d06..0a18346b9fe 100644 --- a/src/main/java/controller/MainController.java +++ b/src/main/java/controller/MainController.java @@ -15,8 +15,13 @@ public class MainController { private final GameRoomController gameRoomController = new GameRoomController(new GameRoomService(new RoomDaoImpl())); - private final ChessGameController chessGameController = new ChessGameController(new ChessGameService( - new PieceDaoImpl(), new GameStateDaoImpl())); + private final ChessGameController chessGameController + = new ChessGameController( + new ChessGameService( + new PieceDaoImpl(), + new GameStateDaoImpl() + ) + ); private final UserController userController = new UserController(new UserService(new UserDaoImpl())); public void run() { diff --git a/src/main/java/controller/room/command/SelectRoomOnRoomCommand.java b/src/main/java/controller/room/command/SelectRoomOnRoomCommand.java index 56122ff3661..3db83c2ddb8 100644 --- a/src/main/java/controller/room/command/SelectRoomOnRoomCommand.java +++ b/src/main/java/controller/room/command/SelectRoomOnRoomCommand.java @@ -34,7 +34,7 @@ private void validateRoomIdFormat(final String input) { private void validateRoomIdRunning(final List validRooms, final String input) { boolean isRunningRoomNotFound = validRooms.stream() - .noneMatch(room -> room.room_id() == Integer.parseInt(input)); + .noneMatch(room -> room.roomId() == Integer.parseInt(input)); if (isRunningRoomNotFound) { throw new IllegalArgumentException(); } diff --git a/src/main/java/dto/RoomDto.java b/src/main/java/dto/RoomDto.java index 0da5e418f65..ed1b23d8766 100644 --- a/src/main/java/dto/RoomDto.java +++ b/src/main/java/dto/RoomDto.java @@ -1,4 +1,4 @@ package dto; -public record RoomDto(int room_id) { +public record RoomDto(int roomId) { } diff --git a/src/main/java/service/ChessGameService.java b/src/main/java/service/ChessGameService.java index 72d275b2326..04a01e02014 100644 --- a/src/main/java/service/ChessGameService.java +++ b/src/main/java/service/ChessGameService.java @@ -32,24 +32,24 @@ public ChessGame initializeChessGame(final RoomDto roomDto) { public void saveChessGame(final ChessGame chessGame, final RoomDto roomDto) { if (chessGame.isGameOver()) { - updateState(new StateDto("GAMEOVER", roomDto.room_id())); + updateState(new StateDto("GAMEOVER", roomDto.roomId())); return; } updatePieces(roomDto, chessGame.getBoard().getPieces()); - updateState(new StateDto(chessGame.getTurn().name(), roomDto.room_id())); + updateState(new StateDto(chessGame.getTurn().name(), roomDto.roomId())); } private List loadPreviousPieces(final RoomDto roomDto) { - return pieceDao.findPieceByGameId(roomDto.room_id()); + return pieceDao.findPieceByGameId(roomDto.roomId()); } private StateDto loadPreviousState(final RoomDto roomDto) { - return gameStateDao.findByGameId(roomDto.room_id()) + return gameStateDao.findByGameId(roomDto.roomId()) .orElseThrow(NoSuchElementException::new); } private void updatePieces(final RoomDto roomDto, final List pieceDtos) { - pieceDao.deleteAllByGameId(roomDto.room_id()); + pieceDao.deleteAllByGameId(roomDto.roomId()); for (final PieceDto pieceDto : pieceDtos) { pieceDao.add(roomDto, pieceDto); } diff --git a/src/main/java/view/MessageResolver.java b/src/main/java/view/MessageResolver.java index a7ca6c97760..9cbf5417ea5 100644 --- a/src/main/java/view/MessageResolver.java +++ b/src/main/java/view/MessageResolver.java @@ -109,13 +109,13 @@ private String resolveRooms(List rooms) { String roomGuideHeaderMessage = String.format("> 입장할 방 선택 : %s 방번호 - 예 %s 1", ROOM_SELECTION.message(), ROOM_SELECTION.message()); String roomListMessage = "> 방 목록 : " + rooms.stream() - .map(room -> String.valueOf(room.room_id())) + .map(room -> String.valueOf(room.roomId())) .collect(Collectors.joining(", ")); return String.join(LINE_SEPARATOR, roomGuideHeaderMessage, roomListMessage); } public String resolveEnteringRoomMessage(RoomDto roomDto) { - return roomDto.room_id() + "번 방에 입장합니다."; + return roomDto.roomId() + "번 방에 입장합니다."; } public String resolveUserNameInputMessage() { diff --git a/src/test/java/repository/PieceMockDao.java b/src/test/java/repository/PieceMockDao.java index 4efce847254..8c766ebaf55 100644 --- a/src/test/java/repository/PieceMockDao.java +++ b/src/test/java/repository/PieceMockDao.java @@ -31,7 +31,7 @@ public void deleteAllByGameId(final int gameId) { } private String generateKey(RoomDto room, PieceDto piece) { - return room.room_id() + "-" + piece.boardFile() + "-" + piece.boardRank(); + return room.roomId() + "-" + piece.boardFile() + "-" + piece.boardRank(); } private int extractGameIdFromKey(String key) { diff --git a/src/test/java/repository/RoomMockDao.java b/src/test/java/repository/RoomMockDao.java index ed8747b4c03..e74b144aeda 100644 --- a/src/test/java/repository/RoomMockDao.java +++ b/src/test/java/repository/RoomMockDao.java @@ -26,7 +26,7 @@ public void add(UserDto userDto, RoomDto roomDto) { public Optional addNewRoom(UserDto userDto) { int newRoomId = roomRepository.keySet() .stream() - .mapToInt(RoomDto::room_id) + .mapToInt(RoomDto::roomId) .max() .orElse(0) + 1; RoomDto newRoom = new RoomDto(newRoomId); @@ -36,14 +36,14 @@ public Optional addNewRoom(UserDto userDto) { public Optional find(final String roomId) { return roomRepository.keySet().stream() - .filter(room -> room.room_id() == Integer.parseInt(roomId)) + .filter(room -> room.roomId() == Integer.parseInt(roomId)) .findFirst(); } public List findActiveRoomAll(final UserDto user) { return roomRepository.entrySet().stream() .filter(entry -> entry.getValue().equals(user)) - .filter(entry -> !Objects.equals(turnRepository.get(entry.getKey().room_id()).state(), "GAMEOVER")) + .filter(entry -> !Objects.equals(turnRepository.get(entry.getKey().roomId()).state(), "GAMEOVER")) .map(Map.Entry::getKey) .toList(); } diff --git a/src/test/java/service/GameRoomServiceTest.java b/src/test/java/service/GameRoomServiceTest.java index b5d97bb5637..be5585db203 100644 --- a/src/test/java/service/GameRoomServiceTest.java +++ b/src/test/java/service/GameRoomServiceTest.java @@ -28,9 +28,9 @@ class GameRoomServiceTest { room3, MANGCHO); private final Map turnRepository = Map.of( - room1.room_id(), new StateDto("GAMEOVER", room1.room_id()), - room2.room_id(), new StateDto("WHITE", room2.room_id()), - room3.room_id(), new StateDto("BLACK", room3.room_id())); + room1.roomId(), new StateDto("GAMEOVER", room1.roomId()), + room2.roomId(), new StateDto("WHITE", room2.roomId()), + room3.roomId(), new StateDto("BLACK", room3.roomId())); @Test void 활성화된_모든_방을_불러온다() { From 5e09e5370bd321197e99d46a54bc058c5f2d5a82 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Wed, 3 Apr 2024 22:35:33 +0900 Subject: [PATCH 90/94] =?UTF-8?q?refactor:=20=EB=94=94=EB=AF=B8=ED=84=B0?= =?UTF-8?q?=20=EB=B2=95=EC=B9=99=EC=97=90=20=EB=94=B0=EB=9D=BC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95,=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/MainController.java | 4 ++-- src/main/java/controller/game/ChessGameController.java | 4 +++- src/main/java/controller/room/GameRoomController.java | 6 ++++-- src/main/java/controller/user/UserController.java | 6 ++++-- src/main/java/service/ChessGameService.java | 9 +++++++-- 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/main/java/controller/MainController.java b/src/main/java/controller/MainController.java index 0a18346b9fe..62357f1a372 100644 --- a/src/main/java/controller/MainController.java +++ b/src/main/java/controller/MainController.java @@ -25,9 +25,9 @@ public class MainController { private final UserController userController = new UserController(new UserService(new UserDaoImpl())); public void run() { - UserDto user = userController.run(); + UserDto user = userController.loadUser(); while (true) { - RoomDto room = gameRoomController.run(user); + RoomDto room = gameRoomController.loadRoom(user); chessGameController.run(room); } } diff --git a/src/main/java/controller/game/ChessGameController.java b/src/main/java/controller/game/ChessGameController.java index 23c8361d584..d5bedd1c854 100644 --- a/src/main/java/controller/game/ChessGameController.java +++ b/src/main/java/controller/game/ChessGameController.java @@ -1,5 +1,6 @@ package controller.game; +import controller.game.command.GameCommand; import domain.ChessGame; import dto.RoomDto; import service.ChessGameService; @@ -24,7 +25,8 @@ public void run(RoomDto roomDto) { private void readCommandUntilValid(ChessGame chessGame) { try { - InputView.readGameCommand().execute(chessGame); + GameCommand command = InputView.readGameCommand(); + command.execute(chessGame); } catch (Exception e) { OutputView.printErrorMessage(e); readCommandUntilValid(chessGame); diff --git a/src/main/java/controller/room/GameRoomController.java b/src/main/java/controller/room/GameRoomController.java index 4b43f3bbd48..8fb1be50fc8 100644 --- a/src/main/java/controller/room/GameRoomController.java +++ b/src/main/java/controller/room/GameRoomController.java @@ -1,5 +1,6 @@ package controller.room; +import controller.room.command.RoomCommand; import dto.RoomDto; import dto.UserDto; import service.GameRoomService; @@ -15,7 +16,7 @@ public GameRoomController(GameRoomService roomService) { this.roomService = roomService; } - public RoomDto run(UserDto user) { + public RoomDto loadRoom(UserDto user) { List rooms = roomService.loadActiveRoomAll(user); OutputView.printGameRoomGuideMessage(rooms); @@ -26,7 +27,8 @@ public RoomDto run(UserDto user) { private RoomDto readCommandUntilValid(UserDto user, List rooms) { try { - return InputView.readRoomCommand(rooms).execute(roomService, user); + RoomCommand command = InputView.readRoomCommand(rooms); + return command.execute(roomService, user); } catch (IllegalArgumentException e) { OutputView.printErrorMessage(e); return readCommandUntilValid(user, rooms); diff --git a/src/main/java/controller/user/UserController.java b/src/main/java/controller/user/UserController.java index beadd5ceb39..7a2bbc24818 100644 --- a/src/main/java/controller/user/UserController.java +++ b/src/main/java/controller/user/UserController.java @@ -1,5 +1,6 @@ package controller.user; +import controller.user.command.UserCommand; import dto.UserDto; import service.UserService; import view.InputView; @@ -12,7 +13,7 @@ public UserController(UserService userService) { this.userService = userService; } - public UserDto run() { + public UserDto loadUser() { OutputView.printUserNameInputMessage(); UserDto user = readCommandUntilValid(); OutputView.printUserNameMessage(user); @@ -21,7 +22,8 @@ public UserDto run() { private UserDto readCommandUntilValid() { try { - return InputView.readUserCommand().execute(userService); + UserCommand command = InputView.readUserCommand(); + return command.execute(userService); } catch (IllegalArgumentException e) { OutputView.printErrorMessage(e); return readCommandUntilValid(); diff --git a/src/main/java/service/ChessGameService.java b/src/main/java/service/ChessGameService.java index 04a01e02014..3ac75999b75 100644 --- a/src/main/java/service/ChessGameService.java +++ b/src/main/java/service/ChessGameService.java @@ -3,7 +3,9 @@ import database.dao.GameStateDao; import database.dao.PieceDao; import domain.ChessGame; +import domain.board.ChessBoard; import domain.board.ChessBoardFactory; +import domain.piece.Color; import dto.PieceDto; import dto.RoomDto; import dto.StateDto; @@ -35,8 +37,11 @@ public void saveChessGame(final ChessGame chessGame, final RoomDto roomDto) { updateState(new StateDto("GAMEOVER", roomDto.roomId())); return; } - updatePieces(roomDto, chessGame.getBoard().getPieces()); - updateState(new StateDto(chessGame.getTurn().name(), roomDto.roomId())); + + final ChessBoard board = chessGame.getBoard(); + Color turn = chessGame.getTurn(); + updatePieces(roomDto, board.getPieces()); + updateState(new StateDto(turn.name(), roomDto.roomId())); } private List loadPreviousPieces(final RoomDto roomDto) { From 172b4535a3dd6280e7992627f8b2eb4111221e0d Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Wed, 3 Apr 2024 22:40:45 +0900 Subject: [PATCH 91/94] =?UTF-8?q?refactor:=20isEmpty()=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/game/command/EndOnGameCommand.java | 4 +--- src/main/java/controller/game/command/StartOnGameCommand.java | 4 +--- .../java/controller/game/command/StatusOnGameCommand.java | 4 +--- .../java/controller/room/command/NewRoomOnRoomCommand.java | 4 +--- 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/main/java/controller/game/command/EndOnGameCommand.java b/src/main/java/controller/game/command/EndOnGameCommand.java index ef7883fba92..6c966f54f37 100644 --- a/src/main/java/controller/game/command/EndOnGameCommand.java +++ b/src/main/java/controller/game/command/EndOnGameCommand.java @@ -5,14 +5,12 @@ import java.util.List; public class EndOnGameCommand implements GameCommand { - private static final int ARGUMENT_SIZE = 0; - public EndOnGameCommand(final List arguments) { validateArgumentSize(arguments); } private void validateArgumentSize(final List arguments) { - if (arguments.size() != ARGUMENT_SIZE) { + if (!arguments.isEmpty()) { throw new IllegalArgumentException(); } } diff --git a/src/main/java/controller/game/command/StartOnGameCommand.java b/src/main/java/controller/game/command/StartOnGameCommand.java index dd619c1da78..c7df39f16c0 100644 --- a/src/main/java/controller/game/command/StartOnGameCommand.java +++ b/src/main/java/controller/game/command/StartOnGameCommand.java @@ -6,14 +6,12 @@ import java.util.List; public class StartOnGameCommand implements GameCommand { - private static final int ARGUMENT_SIZE = 0; - public StartOnGameCommand(final List arguments) { validateArgumentSize(arguments); } private void validateArgumentSize(final List arguments) { - if (arguments.size() != ARGUMENT_SIZE) { + if (!arguments.isEmpty()) { throw new IllegalArgumentException(); } } diff --git a/src/main/java/controller/game/command/StatusOnGameCommand.java b/src/main/java/controller/game/command/StatusOnGameCommand.java index 4be90a202b9..46cba28f6e6 100644 --- a/src/main/java/controller/game/command/StatusOnGameCommand.java +++ b/src/main/java/controller/game/command/StatusOnGameCommand.java @@ -7,14 +7,12 @@ import java.util.List; public class StatusOnGameCommand implements GameCommand { - private static final int ARGUMENT_SIZE = 0; - public StatusOnGameCommand(final List arguments) { validateArgumentSize(arguments); } private void validateArgumentSize(final List arguments) { - if (arguments.size() != ARGUMENT_SIZE) { + if (!arguments.isEmpty()) { throw new IllegalArgumentException(); } } diff --git a/src/main/java/controller/room/command/NewRoomOnRoomCommand.java b/src/main/java/controller/room/command/NewRoomOnRoomCommand.java index fb9abfb7e51..4c4344a545e 100644 --- a/src/main/java/controller/room/command/NewRoomOnRoomCommand.java +++ b/src/main/java/controller/room/command/NewRoomOnRoomCommand.java @@ -7,14 +7,12 @@ import java.util.List; public class NewRoomOnRoomCommand implements RoomCommand { - private static final int ARGUMENT_SIZE = 0; - public NewRoomOnRoomCommand(final List arguments) { validateArgumentSize(arguments); } private void validateArgumentSize(final List arguments) { - if (arguments.size() != ARGUMENT_SIZE) { + if (!arguments.isEmpty()) { throw new IllegalArgumentException(); } } From 2ba8f3f69b67c1ef2cd04976c7000106151c522c Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Wed, 3 Apr 2024 22:46:32 +0900 Subject: [PATCH 92/94] =?UTF-8?q?refactor:=20=EA=B0=9C=ED=96=89=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/position/Position.java | 6 ++++-- src/main/java/service/GameRoomService.java | 5 ++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/domain/position/Position.java b/src/main/java/domain/position/Position.java index adb8e67c9fa..04189fca0f0 100644 --- a/src/main/java/domain/position/Position.java +++ b/src/main/java/domain/position/Position.java @@ -7,8 +7,10 @@ public class Position { private final Rank rank; public Position(final String fileAndRank) { - this(File.fromName(fileAndRank.substring(0, 1)), - Rank.fromNumber(Integer.parseInt(fileAndRank.substring(1)))); + this( + File.fromName(fileAndRank.substring(0, 1)), + Rank.fromNumber(Integer.parseInt(fileAndRank.substring(1))) + ); } public Position(final File file, final Rank rank) { diff --git a/src/main/java/service/GameRoomService.java b/src/main/java/service/GameRoomService.java index 0f989f5eaca..56b204345a0 100644 --- a/src/main/java/service/GameRoomService.java +++ b/src/main/java/service/GameRoomService.java @@ -5,7 +5,6 @@ import dto.UserDto; import java.util.List; -import java.util.Optional; public class GameRoomService { private final RoomDao roomDao; @@ -19,8 +18,8 @@ public List loadActiveRoomAll(final UserDto user) { } public RoomDto createNewRoom(final UserDto user) { - final Optional room = roomDao.addNewRoom(user); - return room.orElseThrow(IllegalStateException::new); + return roomDao.addNewRoom(user) + .orElseThrow(IllegalStateException::new); } public RoomDto findRoomById(final String roomId) { From 0fa658a60cc90af591d90bd95cbd843b90c81e5e Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Wed, 3 Apr 2024 23:06:58 +0900 Subject: [PATCH 93/94] =?UTF-8?q?fix:=20=EB=AC=B4=ED=95=9C=20=EB=B0=98?= =?UTF-8?q?=EB=B3=B5=EB=90=98=EB=8A=94=20=EC=96=B4=ED=94=8C=EB=A6=AC?= =?UTF-8?q?=EC=BC=80=EC=9D=B4=EC=85=98=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/controller/MainController.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/controller/MainController.java b/src/main/java/controller/MainController.java index 62357f1a372..f37658d9995 100644 --- a/src/main/java/controller/MainController.java +++ b/src/main/java/controller/MainController.java @@ -26,9 +26,7 @@ public class MainController { public void run() { UserDto user = userController.loadUser(); - while (true) { - RoomDto room = gameRoomController.loadRoom(user); - chessGameController.run(room); - } + RoomDto room = gameRoomController.loadRoom(user); + chessGameController.run(room); } } From b62df02dbfcb123b6a0fc1bdef26f56f21c94ebd Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Thu, 4 Apr 2024 17:54:01 +0900 Subject: [PATCH 94/94] =?UTF-8?q?refactor:=20=ED=95=A8=EC=88=98=ED=98=95?= =?UTF-8?q?=20=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=EB=A1=9C=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/view/command/GameCommandType.java | 12 ++++++++---- src/main/java/view/command/RoomCommandType.java | 12 ++++++++---- src/main/java/view/command/UserCommandType.java | 12 ++++++++---- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/main/java/view/command/GameCommandType.java b/src/main/java/view/command/GameCommandType.java index 1df65db739b..c2f5436acc7 100644 --- a/src/main/java/view/command/GameCommandType.java +++ b/src/main/java/view/command/GameCommandType.java @@ -1,14 +1,13 @@ package view.command; -import controller.game.command.GameCommand; import controller.game.command.EndOnGameCommand; +import controller.game.command.GameCommand; import controller.game.command.MoveOnGameCommand; import controller.game.command.StartOnGameCommand; import controller.game.command.StatusOnGameCommand; import java.util.Arrays; import java.util.List; -import java.util.function.Function; public enum GameCommandType { START("start", StartOnGameCommand::new), @@ -17,9 +16,9 @@ public enum GameCommandType { MOVE("move", MoveOnGameCommand::new); private final String command; - private final Function, GameCommand> mapper; + private final CommandMapper mapper; - GameCommandType(final String command, final Function, GameCommand> mapper) { + GameCommandType(final String command, final CommandMapper mapper) { this.command = command; this.mapper = mapper; } @@ -36,4 +35,9 @@ public static GameCommand getCommand(final CommandInput input) { public String message() { return this.command; } + + @FunctionalInterface + private interface CommandMapper { + GameCommand apply(List arguments); + } } diff --git a/src/main/java/view/command/RoomCommandType.java b/src/main/java/view/command/RoomCommandType.java index fb0a63b5f2a..0d3d93ad3af 100644 --- a/src/main/java/view/command/RoomCommandType.java +++ b/src/main/java/view/command/RoomCommandType.java @@ -1,22 +1,21 @@ package view.command; -import controller.room.command.RoomCommand; import controller.room.command.NewRoomOnRoomCommand; +import controller.room.command.RoomCommand; import controller.room.command.SelectRoomOnRoomCommand; import dto.RoomDto; import java.util.Arrays; import java.util.List; -import java.util.function.BiFunction; public enum RoomCommandType { NEW_ROOM("new", (arguments, rooms) -> new NewRoomOnRoomCommand(arguments)), ROOM_SELECTION("room", SelectRoomOnRoomCommand::new); private final String command; - private final BiFunction, List, RoomCommand> mapper; + private final CommandMapper mapper; - RoomCommandType(final String command, final BiFunction, List, RoomCommand> mapper) { + RoomCommandType(final String command, final CommandMapper mapper) { this.command = command; this.mapper = mapper; } @@ -33,4 +32,9 @@ public static RoomCommand getCommand(final CommandInput input, final List arguments, List rooms); + } } diff --git a/src/main/java/view/command/UserCommandType.java b/src/main/java/view/command/UserCommandType.java index 300fca66a10..a237de049c8 100644 --- a/src/main/java/view/command/UserCommandType.java +++ b/src/main/java/view/command/UserCommandType.java @@ -1,19 +1,18 @@ package view.command; -import controller.user.command.UserCommand; import controller.user.command.FindUserOnDemand; +import controller.user.command.UserCommand; import java.util.Arrays; import java.util.List; -import java.util.function.Function; public enum UserCommandType { FIND_USER("user", FindUserOnDemand::new); private final String command; - private final Function, UserCommand> mapper; + private final CommandMapper mapper; - UserCommandType(final String command, final Function, UserCommand> mapper) { + UserCommandType(final String command, final CommandMapper mapper) { this.command = command; this.mapper = mapper; } @@ -30,4 +29,9 @@ public static UserCommand getCommand(final CommandInput input) { public String message() { return this.command; } + + @FunctionalInterface + private interface CommandMapper { + UserCommand apply(List arguments); + } }