From 73ef8478975fbe67dcd61b68bb9f37373554ca0e Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Wed, 25 Mar 2026 00:19:03 +0900 Subject: [PATCH 01/82] docs: write README.md --- README.md | 145 ++++++++++++++++++++++++++++++++++ docs/images/class-diagram.png | Bin 0 -> 104455 bytes docs/images/flowchart.png | Bin 0 -> 271282 bytes 3 files changed, 145 insertions(+) create mode 100644 docs/images/class-diagram.png create mode 100644 docs/images/flowchart.png diff --git a/README.md b/README.md index 9775dda0ae..d1d1e37236 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,148 @@ # java-janggi 장기 미션 저장소 + + +## 구현 흐름 + +전체 게임 진행 흐름은 아래 플로우 차트를 기준으로 설계했다. + +- 보드 세팅 후 턴이 시작된다. +- 현재 턴의 플레이어는 자신의 생존 기물 중 하나를 선택한다. +- 선택한 기물의 이동 가능 후보 위치를 확인한 뒤 목적지를 선택한다. +- 이동 이후 포획 여부, 점수, 장군/외통수 여부를 순서대로 판정한다. +- 시간 초과 여부를 확인하고, 종료 조건이 아니라면 현재 장기판 상태를 출력한 뒤 턴을 교체한다. + +## 프로젝트 구조 + + + + + + +
+ + + +
+ 게임 흐름도 +
+ + + +
+ 클래스 다이어그램 +
+ +## 기능 구현 리스트 + +- [ ] 장기판에서 사용할 좌표 체계를 정의 + - `Pos`, `Direction`, `Route`가 어떤 의미를 가지는지 먼저 확정 + - 좌표 범위, 방향 표현 방식, 경로의 시작/끝/중간 위치를 어떻게 다룰지 결정 + +- [ ] 게임에서 사용할 분류 체계 정의 + - 전역에서 공통으로 사용하는 값의 종류를 정리 + - ex) 팀 구분, 기물 종류, 게임 상태 + +- [ ] 기물의 이동 규칙을 어떤 방식으로 표현할지 확정 + - 이동 규칙을 단순 방향 목록으로 표현할지, 경로(Route) 생성까지 포함할지 결정 + +- [ ] 기물이 자신의 팀, 종류, 이동 규칙을 가지도록 공통 구조를 만든다 + - 모든 기물이 공통적으로 가져야 하는 속성과 동작을 정의 + +- [ ] 규칙이 단순한 기물의 이동 가능 후보 경로를 계산 + - 비교적 단순한 기물부터 시작 ex) `졸`, `사`, `왕` + - 전체 흐름 빠르게 검증 + +- [ ] 규칙이 복잡한 기물의 이동 가능 후보 경로를 계산 + - 경로와 중간 칸의 영향을 크게 받는 기물의 규칙을 구현 ex) `차`, `마`, `상` + +- [ ] 각 기물을 게임에서 사용할 수 있는 형태로 구체화 + - 상, 마, 차, 졸, 사, 왕이 각각 생성 가능하도록 + - 생성 시 팀 정보와 이동 규칙이 자연스럽게 연결되록 + +- [ ] 장기판의 현재 기물 배치 상태 저장, 조회 기능 구현 + - 특정 위치에 어떤 기물이 있는지 확인할 수 있도록 + +- [ ] 장기판에 기물을 배치하고 이동하는 기능 구현 + - 초기 배치와 실제 게임 중 이동 모두 처리할 수 있도록 + - [ ] 이동 후 보드 상태 갱신 + +- [ ] 장기판이 빈 칸 여부와 경로 차단 여부를 판단하는 기능 구현 + - 단순히 목적지만 보는 것이 아니라, 이동 경로 중간 칸도 검사할 수 있도록 + +- [ ] 기물이 선택한 목적지로 실제 이동 가능한지 판정하는 기능 구현 + - 기물이 만든 이동 후보와 현재 장기판 상태를 함께 고려 + - 아군이 있는 칸인지, 적군이 있는 칸인지, 중간 경로가 막혔는지 등을 종합적으로 판정 + +- [ ] 게임 시작 시 장기판을 초기 상태로 세팅 + - 초기 기물 생성 + - 초기 배치 좌표 정의 + - 초기 장기판 세팅 + +- [ ] 플레이어가 자신의 팀과 기물 집합을 관리 + - 플레이어는 게임에 참가하는 주체 -> 턴, 승패의 주체 + +- [ ] 플레이어별로 생존 기물과 잡은 기물을 관리할 수 있도록 + - 점수 계산에 필요한 정보 유지 + - 기물 관리 책임은 도메인 단위로 래핑 + +- [ ] 포획이 발생했을 때 게임 상태 갱신 + - 이동한 목적지에 상대 기물이 있으면 포획으로 처리 + - [ ] 보드 상태와 플레이어의 기물 목록 함께 갱신 + +- [ ] 현재 보드 상태를 기준으로 플레이어의 점수를 계산 + - 시간 초과 시 어떤 기물이 살아 있는지, 잡혔는지 기준으로 점수를 계산 + +- [ ] 턴 교체 + - 현재 턴 플레이어 확인 + - 다음 턴 플레이어 확인 + +- [ ] 최소 플레이가 가능한 게임 루프 생성 + - 현재 턴 플레이어의 기물 목록 출력 + - 기물 선택 입력 처리 + - 이동 후보 위치 출력 + - 목적지 선택 입력 처리 + - 이동 수행 + - 현재 장기판 상태 출력 + - 턴 교체 + - 장군/외통수/시간 제한 배제하고 한턴 씩은 진행 되도록 + +- [ ] 잘못된 입력이 들어왔을 때 같은 흐름 안에서 다시 선택할 수 있도록 + - [ ] 존재하지 않는 기물 선택 + - [ ] 이동 불가능한 목적지 선택 + - [ ] 잘못된 형식의 입력 처리 + - [ ] 입력 오류가 났을 때 게임 전체가 깨지지 않고 현재 단계만 다시 진행되도록 + +- [ ] 장군 멍군 구현 + - 현재 보드 상태 기준으로 장군 여부를 판단 + - 한 턴 종료 후 필수적으로 확인 + +- [ ] 장군 상태에서 벗어날 수 있는 수가 있는지 판정할 수 있도록 + - 외통수 여부를 판단 + - 외통수면 즉시 승리 및 게임 종료로 연결 + +- [ ] 게임 종료 조건이 발생했을 때 게임 종료하도록 + - 외통수로 종료 + - 점수 판정으로 종료 + - 종료 시 더 이상 턴이 진행되지 않도록 상태 변경 + +- [ ] 시간 제한 규칙을 게임 흐름에 포함 + - 전체 시간 기준 + - 게임 시작 후 시간 측정 시작, 매 턴 종료 시 보드 상태 출력 후 시간 공지 + +- [ ] 시간 초과 시 점수로 승패를 판정 + - 시간 초과 감지 + - 각 플레이어 점수 계산 + - 승패 판정 + - 게임 종료 처리 + +--- +## 미션 중 기록 + +- 상태 위치를 결정할 때 고민한 순간 1회 +- 불변/캡슐화를 적용한 코드 1곳 +- 규칙 적용으로 변경한 설계 1곳 +- 조건문을 다형성으로 대체한 코드 1곳 +- 인터페이스/추상 클래스를 도입한 이유 +- 새 기물 추가 시 변경 범위 테스트 (가상으로) \ No newline at end of file diff --git a/docs/images/class-diagram.png b/docs/images/class-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..9ef20f4e7561ab304ef37580455ce86fdabf95a5 GIT binary patch literal 104455 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 Date: Wed, 25 Mar 2026 16:36:19 +0900 Subject: [PATCH 02/82] docs : update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 테스트 시나리오 작성 - 기능 구현 리스트 순서 수정 --- README.md | 246 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 165 insertions(+), 81 deletions(-) diff --git a/README.md b/README.md index d1d1e37236..41f956fac0 100644 --- a/README.md +++ b/README.md @@ -34,115 +34,199 @@ -## 기능 구현 리스트 - -- [ ] 장기판에서 사용할 좌표 체계를 정의 - - `Pos`, `Direction`, `Route`가 어떤 의미를 가지는지 먼저 확정 - - 좌표 범위, 방향 표현 방식, 경로의 시작/끝/중간 위치를 어떻게 다룰지 결정 +### 사이클1 구현 내용 -- [ ] 게임에서 사용할 분류 체계 정의 - - 전역에서 공통으로 사용하는 값의 종류를 정리 - - ex) 팀 구분, 기물 종류, 게임 상태 +- [ ] [기능구현] 게임에서 사용할 분류 체계 정의 + - 전역에서 공통으로 사용하는 값의 종류를 정리 + - ex) 팀 구분, 기물 종류, 게임 상태 -- [ ] 기물의 이동 규칙을 어떤 방식으로 표현할지 확정 - - 이동 규칙을 단순 방향 목록으로 표현할지, 경로(Route) 생성까지 포함할지 결정 +- [ ] [기능구현][예외처리] 장기판에서 사용할 좌표 체계를 정의 + - `Position`, `Direction`, `Route`가 어떤 의미를 가지는지 먼저 확정 + - 좌표 범위, 방향 표현 방식, 경로의 시작/끝/중간 위치를 어떻게 다룰지 결정 + - [예외처리] 유효하지 않은 좌표 생성 방지 -- [ ] 기물이 자신의 팀, 종류, 이동 규칙을 가지도록 공통 구조를 만든다 - - 모든 기물이 공통적으로 가져야 하는 속성과 동작을 정의 +- [ ] [기능구현] 기물의 이동 규칙을 어떤 방식으로 표현할지 확정 + - 이동 규칙을 단순 방향 목록으로 표현할지, 경로(Route) 생성까지 포함할지 결정 + - 궁성 영역 관련 규칙은 제외 -- [ ] 규칙이 단순한 기물의 이동 가능 후보 경로를 계산 - - 비교적 단순한 기물부터 시작 ex) `졸`, `사`, `왕` - - 전체 흐름 빠르게 검증 +- [ ] [기능구현] 기물이 자신의 팀, 종류, 이동 규칙을 가지도록 공통 구조를 만든다 + - 모든 기물이 공통적으로 가져야 하는 속성과 동작을 정의 -- [ ] 규칙이 복잡한 기물의 이동 가능 후보 경로를 계산 - - 경로와 중간 칸의 영향을 크게 받는 기물의 규칙을 구현 ex) `차`, `마`, `상` +- [ ] [기능구현] 각 기물을 게임에서 사용할 수 있는 형태로 구체화 + - 상, 마, 차, 졸, 사, 왕이 각각 생성 가능하도록 + - 생성 시 팀 정보와 이동 규칙이 자연스럽게 연결되도록 -- [ ] 각 기물을 게임에서 사용할 수 있는 형태로 구체화 - - 상, 마, 차, 졸, 사, 왕이 각각 생성 가능하도록 - - 생성 시 팀 정보와 이동 규칙이 자연스럽게 연결되록 +- [ ] [상태관리][예외처리] 장기판의 현재 기물 배치 상태 저장, 조회 기능 구현 + - 특정 위치에 어떤 기물이 있는지 확인할 수 있도록 + - [예외처리] 존재하지 않는 위치 조회 방지 -- [ ] 장기판의 현재 기물 배치 상태 저장, 조회 기능 구현 - - 특정 위치에 어떤 기물이 있는지 확인할 수 있도록 +- [ ] [초기화] 게임 시작 시 장기판을 초기 상태로 세팅 + - 초기 기물 생성 + - 초기 배치 좌표 정의 + - 초기 장기판 세팅 -- [ ] 장기판에 기물을 배치하고 이동하는 기능 구현 - - 초기 배치와 실제 게임 중 이동 모두 처리할 수 있도록 - - [ ] 이동 후 보드 상태 갱신 +- [ ] [기능구현] 규칙이 단순한 기물의 이동 가능 후보 경로를 계산 + - 비교적 단순한 기물부터 시작 ex) `졸`, `사`, `왕` + - 궁성 영역 관련 규칙은 제외 + - 전체 흐름 빠르게 검증 -- [ ] 장기판이 빈 칸 여부와 경로 차단 여부를 판단하는 기능 구현 - - 단순히 목적지만 보는 것이 아니라, 이동 경로 중간 칸도 검사할 수 있도록 +- [ ] [기능구현] 규칙이 복잡한 기물의 이동 가능 후보 경로를 계산 + - 경로와 중간 칸의 영향을 크게 받는 기물의 규칙을 구현 ex) `차`, `마`, `상` -- [ ] 기물이 선택한 목적지로 실제 이동 가능한지 판정하는 기능 구현 - - 기물이 만든 이동 후보와 현재 장기판 상태를 함께 고려 - - 아군이 있는 칸인지, 적군이 있는 칸인지, 중간 경로가 막혔는지 등을 종합적으로 판정 +- [ ] [판정] 장기판이 빈 칸 여부와 경로 차단 여부를 판단하는 기능 구현 + - 단순히 목적지만 보는 것이 아니라, 이동 경로 중간 칸도 검사할 수 있도록 -- [ ] 게임 시작 시 장기판을 초기 상태로 세팅 - - 초기 기물 생성 - - 초기 배치 좌표 정의 - - 초기 장기판 세팅 +- [ ] [판정][예외처리] 기물이 선택한 목적지로 실제 이동 가능한지 판정하는 기능 구현 + - 기물이 만든 이동 후보와 현재 장기판 상태를 함께 고려 + - 아군이 있는 칸인지, 적군이 있는 칸인지, 중간 경로가 막혔는지 등을 종합적으로 판정 + - 궁성 관련 판정은 제외 + - [예외처리] 이동 불가능한 경우 명확히 거부 -- [ ] 플레이어가 자신의 팀과 기물 집합을 관리 - - 플레이어는 게임에 참가하는 주체 -> 턴, 승패의 주체 +- [ ] [기능구현][상태관리][예외처리] 장기판에 기물을 배치하고 이동하는 기능 구현 + - 초기 배치와 실제 게임 중 이동 모두 처리할 수 있도록 + - [ ] [상태관리] 이동 후 보드 상태 갱신 + - [예외처리] 잘못된 이동 요청(범위 밖, 규칙 위반) 방지 -- [ ] 플레이어별로 생존 기물과 잡은 기물을 관리할 수 있도록 - - 점수 계산에 필요한 정보 유지 - - 기물 관리 책임은 도메인 단위로 래핑 +- [ ] [출력] 초기 장기판 상태를 출력할 수 있도록 + - 1.1단계 초기화 결과를 눈으로 검증할 수 있어야 한다 -- [ ] 포획이 발생했을 때 게임 상태 갱신 - - 이동한 목적지에 상대 기물이 있으면 포획으로 처리 - - [ ] 보드 상태와 플레이어의 기물 목록 함께 갱신 +- [ ] [출력] 특정 기물의 이동 후보 또는 이동 결과를 확인할 수 있도록 + - 1.2단계 이동 규칙 구현 결과를 눈으로 검증할 수 있어야 한다 -- [ ] 현재 보드 상태를 기준으로 플레이어의 점수를 계산 - - 시간 초과 시 어떤 기물이 살아 있는지, 잡혔는지 기준으로 점수를 계산 +--- + +### 사이클2 구현 내용 + +- [ ] [상태관리] 플레이어가 자신의 팀과 기물 집합을 관리 + - 플레이어는 게임에 참가하는 주체 -> 턴, 승패의 주체 + +- [ ] [상태관리] 플레이어별로 생존 기물과 잡은 기물을 관리할 수 있도록 + - 점수 계산에 필요한 정보 유지 + - 기물 관리 책임은 도메인 단위로 래핑 + +- [ ] [기능구현][상태관리] 포획이 발생했을 때 게임 상태 갱신 + - 이동한 목적지에 상대 기물이 있으면 포획으로 처리 + - [ ] [상태관리] 보드 상태와 플레이어의 기물 목록 함께 갱신 + +- [ ] [기능구현] 현재 보드 상태를 기준으로 플레이어의 점수를 계산 + - 시간 초과 시 어떤 기물이 살아 있는지, 잡혔는지 기준으로 점수를 계산 + +- [ ] [게임흐름] 턴 교체 + - 현재 턴 플레이어 확인 + - 다음 턴 플레이어 확인 + +- [ ] [게임흐름][입력][출력] 최소 플레이가 가능한 게임 루프 생성 + - [출력] 현재 턴 플레이어의 기물 목록 출력 + - [입력] 기물 선택 입력 처리 + - [출력] 이동 후보 위치 출력 + - [입력] 목적지 선택 입력 처리 + - [기능구현] 이동 수행 + - [출력] 현재 장기판 상태 출력 + - [게임흐름] 턴 교체 + - 장군/외통수/시간 제한 배제하고 한턴 씩은 진행 되도록 + +- [ ] [입력][게임흐름][예외처리] 잘못된 입력이 들어왔을 때 같은 흐름 안에서 다시 선택할 수 있도록 + - [입력] 존재하지 않는 기물 선택 + - [입력] 이동 불가능한 목적지 선택 + - [입력] 잘못된 형식의 입력 처리 + - [예외처리] 입력 오류 발생 시 재입력 유도 + - [게임흐름] 입력 오류가 났을 때 게임 전체가 깨지지 않고 현재 단계만 다시 진행되도록 + +- [ ] [판정] 장군 멍군 구현 + - 현재 보드 상태 기준으로 장군 여부를 판단 + - 한 턴 종료 후 필수적으로 확인 + +- [ ] [판정] 장군 상태에서 벗어날 수 있는 수가 있는지 판정할 수 있도록 + - 외통수 여부를 판단 + - 외통수면 즉시 승리 및 게임 종료로 연결 + +- [ ] [게임흐름][판정] 게임 종료 조건이 발생했을 때 게임 종료하도록 + - 외통수로 종료 + - 점수 판정으로 종료 + - 종료 시 더 이상 턴이 진행되지 않도록 상태 변경 + +- [ ] [게임흐름] 시간 제한 규칙을 게임 흐름에 포함 + - 전체 시간 기준 + - 게임 시작 후 시간 측정 시작, 매 턴 종료 시 보드 상태 출력 후 시간 공지 + +- [ ] [판정][게임흐름] 시간 초과 시 점수로 승패를 판정 + - 시간 초과 감지 + - 각 플레이어 점수 계산 + - 승패 판정 + - 게임 종료 처리 +--- -- [ ] 턴 교체 - - 현재 턴 플레이어 확인 - - 다음 턴 플레이어 확인 +## TDD 시나리오 -- [ ] 최소 플레이가 가능한 게임 루프 생성 - - 현재 턴 플레이어의 기물 목록 출력 - - 기물 선택 입력 처리 - - 이동 후보 위치 출력 - - 목적지 선택 입력 처리 - - 이동 수행 - - 현재 장기판 상태 출력 - - 턴 교체 - - 장군/외통수/시간 제한 배제하고 한턴 씩은 진행 되도록 +### Position 시나리오 +- 장기판 범위 내의 좌표로 생성할 시 정상 생성. +- 장기판 범위 밖의 좌표로 생성할 시에는 예외 처리 -- [ ] 잘못된 입력이 들어왔을 때 같은 흐름 안에서 다시 선택할 수 있도록 - - [ ] 존재하지 않는 기물 선택 - - [ ] 이동 불가능한 목적지 선택 - - [ ] 잘못된 형식의 입력 처리 - - [ ] 입력 오류가 났을 때 게임 전체가 깨지지 않고 현재 단계만 다시 진행되도록 -- [ ] 장군 멍군 구현 - - 현재 보드 상태 기준으로 장군 여부를 판단 - - 한 턴 종료 후 필수적으로 확인 +### JanggiBoard 시나리오 +- Initializer로부터 초기화되었을 때 모든 말들의 위치정보를 가지고 있다. +- 기물과 해당 기물의 direction규칙을 받으면, 그 기물이 이동 가능한지 여부를 반환한다. + - 범위를 초과하면 '이동'할 수 없다 + - 이동하고자 하는 곳에 다른 기물이 있으면 이동할 수 없다 + +### MoveStrategy 시나리오 +- 각 말들의 MoveStrategy가 우리가 의도한 규칙에 맞게 List이 생성된다. (졸은 옆으로 한 칸, 차는 상하좌우 등..) +- 같은 말 위에 같은 팀 말 안된다. + - 상 + - 마 + - 차 + - 졸 + - 포: intermediateRoutes에서 가져온 말들의 개수가 1이고, 포가 아닌 경우 + - 사 + - 왕 +- 장기 보드와 협력하여 이동 가능한 위치 정보를 받아 루트 정보들을 생성한다. (단, 경로가 막히는 경우는 고려하지 않는다.) + +### Initializer 시나리오 +- 게임 초기의 말들의 위치 정보를 가지고 있다. +- + +```Java +record PieceStartPosition { + // Position(x,y) 형태로 각 말들의 초기정보를 보관 +} +``` + +### Player 시나리오 +- 팀 정보를 가진채로 생성된다. +- 기물저장소를 통해 자신의 기물을 관리한다. + +### PieceStorage + +- 기물과 기물의 현재 상태를 구분하여 저장한다. +- 살아있는 기물을 모아서 반환한다. +- 죽어있는 기물을 모아서 반환한다. +- (후순위) 기물들의 점수를 계산한다. + +### TurnManager 시나리오 +- 현재 턴의 플레이어가 누군지 반환한다. +- 턴이 바뀌면, 현재 플레이어와 다음 플레이어가 스왑된다. +- 턴이 바뀌면, 현재까지 둔 수를 1 올린다. + + +### Runner 시나리오 +- 기물 선택, 이동 위치 선택 입/출력을 진행한다. +- GameStateEnum을 기준으로 게임을 상태에 따라 실행한다. +- Intializer에게 장기판을 세팅하는 함수를 호출한다. +- 플레이어가 정상적인 기물 번호를 선택하고, 정상적인 이동 목적지를 입력하면 JanggiBoard에 움직이는 함수를 호출한다. +- TurnManager에게 턴을 교체하는 함수를 호출한다. +- 플레이어가 정상적인 기물 번호를 선택하지 않으면, 예외를 발생하고 기물 선택으로 돌아온다. +- 플레이어가 정상적인 이동 목적지를 입력하지 않으면, 예외를 발생하고 이동 목적지 입력으로 돌아온다. + -- [ ] 장군 상태에서 벗어날 수 있는 수가 있는지 판정할 수 있도록 - - 외통수 여부를 판단 - - 외통수면 즉시 승리 및 게임 종료로 연결 -- [ ] 게임 종료 조건이 발생했을 때 게임 종료하도록 - - 외통수로 종료 - - 점수 판정으로 종료 - - 종료 시 더 이상 턴이 진행되지 않도록 상태 변경 -- [ ] 시간 제한 규칙을 게임 흐름에 포함 - - 전체 시간 기준 - - 게임 시작 후 시간 측정 시작, 매 턴 종료 시 보드 상태 출력 후 시간 공지 -- [ ] 시간 초과 시 점수로 승패를 판정 - - 시간 초과 감지 - - 각 플레이어 점수 계산 - - 승패 판정 - - 게임 종료 처리 ---- ## 미션 중 기록 - 상태 위치를 결정할 때 고민한 순간 1회 - 불변/캡슐화를 적용한 코드 1곳 - 규칙 적용으로 변경한 설계 1곳 - 조건문을 다형성으로 대체한 코드 1곳 -- 인터페이스/추상 클래스를 도입한 이유 +- 인터페이스/추상경 클래스를 도입한 이유 - 새 기물 추가 시 변경 범위 테스트 (가상으로) \ No newline at end of file From 3f575b4b821bde211b1fb96477aa2ad52d137ef7 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Wed, 25 Mar 2026 16:49:36 +0900 Subject: [PATCH 03/82] test : create Row test code --- src/test/java/RowTest.java | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/test/java/RowTest.java diff --git a/src/test/java/RowTest.java b/src/test/java/RowTest.java new file mode 100644 index 0000000000..3001ceabf2 --- /dev/null +++ b/src/test/java/RowTest.java @@ -0,0 +1,31 @@ +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import org.junit.jupiter.api.Test; + +class RowTest { + @Test + void 유효한_값으로_행_객체가_생성된_경우() { + //given + int input = 3; + + //when + Row row = new Row(input); + + //then + assertThat(row.getValue()).isEqualTo(3); + + } + + + @Test + void 값이_최댓값을_초과하면_예외를_발행한다() { + int input = 19; + + Row row = new Row(input); + + assertThatThrownBy(()->{ + throw new Exception("최대 값은 9입니다."); + }).isInstanceOf(Exception.class); + } + +} \ No newline at end of file From 19be45894a07481d8e4ace025c0b8554a5513250 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Wed, 25 Mar 2026 16:50:55 +0900 Subject: [PATCH 04/82] test : create Column test code --- src/test/java/ColumnTest.java | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/test/java/ColumnTest.java diff --git a/src/test/java/ColumnTest.java b/src/test/java/ColumnTest.java new file mode 100644 index 0000000000..49a4a997f6 --- /dev/null +++ b/src/test/java/ColumnTest.java @@ -0,0 +1,29 @@ +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import org.junit.jupiter.api.Test; + +public class ColumnTest { + @Test + void 유효한_값으로_행_객체가_생성된_경우() { + //given + int input = 3; + + //when + Column row = new Column(input); + + //then + assertThat(row.getValue()).isEqualTo(3); + + } + + + @Test + void 값이_최댓값을_초과하면_예외를_발행한다() { + int input = 19; + + Column row = new Column(input); + + assertThatThrownBy(()->{ + throw new Exception("최대 값은 9입니다."); + }).isInstanceOf(Exception.class); + } +} From 81beec78ae65053d02c5a2837e92841a2c5e0bb9 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Wed, 25 Mar 2026 17:00:56 +0900 Subject: [PATCH 05/82] feat : create Column and Row feat --- src/main/java/Column.java | 19 +++++++++++++++++++ src/main/java/Row.java | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 src/main/java/Column.java create mode 100644 src/main/java/Row.java diff --git a/src/main/java/Column.java b/src/main/java/Column.java new file mode 100644 index 0000000000..f1ee516d3b --- /dev/null +++ b/src/main/java/Column.java @@ -0,0 +1,19 @@ +public class Column { + private static final int COLUMN_MAX_SIZE = 8; + private final int column; + + public Column(int number) { + validateColumn(number); + this.column = number; + } + + public int getValue() { + return this.column; + } + + private void validateColumn(int number) { + if (number > COLUMN_MAX_SIZE) { + throw new IllegalArgumentException("최대 값은 10입니다."); + } + } +} diff --git a/src/main/java/Row.java b/src/main/java/Row.java new file mode 100644 index 0000000000..dec3991f84 --- /dev/null +++ b/src/main/java/Row.java @@ -0,0 +1,19 @@ +public class Row { + private static final int ROW_MAX_SIZE = 8; + private final int row; + + public Row(int number) { + validateRow(number); + this.row = number; + } + + private void validateRow(int number) { + if (number > ROW_MAX_SIZE) { + throw new IllegalArgumentException("최대 값은 9입니다."); + } + } + + public int getValue() { + return this.row; + } +} From 8f98db33ee1d923a9248d965776e404d1f2b3c2d Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Wed, 25 Mar 2026 17:05:36 +0900 Subject: [PATCH 06/82] refactor: modify exception message --- src/main/java/Column.java | 2 +- src/main/java/Position.java | 9 +++++++++ src/test/java/ColumnTest.java | 9 ++++----- src/test/java/RowTest.java | 8 +++----- 4 files changed, 17 insertions(+), 11 deletions(-) create mode 100644 src/main/java/Position.java diff --git a/src/main/java/Column.java b/src/main/java/Column.java index f1ee516d3b..13dcf32e14 100644 --- a/src/main/java/Column.java +++ b/src/main/java/Column.java @@ -13,7 +13,7 @@ public int getValue() { private void validateColumn(int number) { if (number > COLUMN_MAX_SIZE) { - throw new IllegalArgumentException("최대 값은 10입니다."); + throw new IllegalArgumentException("열의 최대 값은 10입니다."); } } } diff --git a/src/main/java/Position.java b/src/main/java/Position.java new file mode 100644 index 0000000000..c1134b3e6b --- /dev/null +++ b/src/main/java/Position.java @@ -0,0 +1,9 @@ +public class Position { + private final Row row; + private final Column column; + + public Position(Row row, Column column) { + this.row = row; + this.column = column; + } +} diff --git a/src/test/java/ColumnTest.java b/src/test/java/ColumnTest.java index 49a4a997f6..061287f98a 100644 --- a/src/test/java/ColumnTest.java +++ b/src/test/java/ColumnTest.java @@ -1,4 +1,5 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import org.junit.jupiter.api.Test; public class ColumnTest { @@ -20,10 +21,8 @@ public class ColumnTest { void 값이_최댓값을_초과하면_예외를_발행한다() { int input = 19; - Column row = new Column(input); - - assertThatThrownBy(()->{ - throw new Exception("최대 값은 9입니다."); - }).isInstanceOf(Exception.class); + assertThatThrownBy(() -> new Column(input)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("열의 최대 값은 10입니다."); } } diff --git a/src/test/java/RowTest.java b/src/test/java/RowTest.java index 3001ceabf2..ad73b11522 100644 --- a/src/test/java/RowTest.java +++ b/src/test/java/RowTest.java @@ -21,11 +21,9 @@ class RowTest { void 값이_최댓값을_초과하면_예외를_발행한다() { int input = 19; - Row row = new Row(input); - - assertThatThrownBy(()->{ - throw new Exception("최대 값은 9입니다."); - }).isInstanceOf(Exception.class); + assertThatThrownBy(() -> new Row(input)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("행의 최대 값은 9입니다."); } } \ No newline at end of file From 8e9a3446525ce3f3c11d7c59b98c2c406622025b Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Wed, 25 Mar 2026 17:08:10 +0900 Subject: [PATCH 07/82] refactor: move to domain package --- src/main/java/{ => domain}/Column.java | 2 ++ src/main/java/{ => domain}/Position.java | 2 ++ src/main/java/{ => domain}/Row.java | 4 +++- src/test/java/{ => domain}/ColumnTest.java | 2 ++ src/test/java/{ => domain}/RowTest.java | 2 ++ 5 files changed, 11 insertions(+), 1 deletion(-) rename src/main/java/{ => domain}/Column.java (96%) rename src/main/java/{ => domain}/Position.java (91%) rename src/main/java/{ => domain}/Row.java (77%) rename src/test/java/{ => domain}/ColumnTest.java (97%) rename src/test/java/{ => domain}/RowTest.java (97%) diff --git a/src/main/java/Column.java b/src/main/java/domain/Column.java similarity index 96% rename from src/main/java/Column.java rename to src/main/java/domain/Column.java index 13dcf32e14..3447651e3f 100644 --- a/src/main/java/Column.java +++ b/src/main/java/domain/Column.java @@ -1,3 +1,5 @@ +package domain; + public class Column { private static final int COLUMN_MAX_SIZE = 8; private final int column; diff --git a/src/main/java/Position.java b/src/main/java/domain/Position.java similarity index 91% rename from src/main/java/Position.java rename to src/main/java/domain/Position.java index c1134b3e6b..543153e776 100644 --- a/src/main/java/Position.java +++ b/src/main/java/domain/Position.java @@ -1,3 +1,5 @@ +package domain; + public class Position { private final Row row; private final Column column; diff --git a/src/main/java/Row.java b/src/main/java/domain/Row.java similarity index 77% rename from src/main/java/Row.java rename to src/main/java/domain/Row.java index dec3991f84..aa4d2fd6d3 100644 --- a/src/main/java/Row.java +++ b/src/main/java/domain/Row.java @@ -1,3 +1,5 @@ +package domain; + public class Row { private static final int ROW_MAX_SIZE = 8; private final int row; @@ -9,7 +11,7 @@ public Row(int number) { private void validateRow(int number) { if (number > ROW_MAX_SIZE) { - throw new IllegalArgumentException("최대 값은 9입니다."); + throw new IllegalArgumentException("행의 최대 값은 9입니다."); } } diff --git a/src/test/java/ColumnTest.java b/src/test/java/domain/ColumnTest.java similarity index 97% rename from src/test/java/ColumnTest.java rename to src/test/java/domain/ColumnTest.java index 061287f98a..66c0072888 100644 --- a/src/test/java/ColumnTest.java +++ b/src/test/java/domain/ColumnTest.java @@ -1,3 +1,5 @@ +package domain; + import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import org.junit.jupiter.api.Test; diff --git a/src/test/java/RowTest.java b/src/test/java/domain/RowTest.java similarity index 97% rename from src/test/java/RowTest.java rename to src/test/java/domain/RowTest.java index ad73b11522..7bb81f58c0 100644 --- a/src/test/java/RowTest.java +++ b/src/test/java/domain/RowTest.java @@ -1,3 +1,5 @@ +package domain; + import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; import org.junit.jupiter.api.Test; From 5863b4807da71bf197d314a21f0a7a8a8b2c1329 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Thu, 26 Mar 2026 13:06:28 +0900 Subject: [PATCH 08/82] =?UTF-8?q?test:=20=EC=95=88=EC=83=81=EC=B0=A8?= =?UTF-8?q?=EB=A6=BC=20=EC=A0=84=EB=9E=B5=20=EA=B5=AC=ED=98=84=EC=B2=B4=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../strategy/formation/InitialFormationStrategyTest.java | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/test/java/strategy/formation/InitialFormationStrategyTest.java diff --git a/src/test/java/strategy/formation/InitialFormationStrategyTest.java b/src/test/java/strategy/formation/InitialFormationStrategyTest.java new file mode 100644 index 0000000000..e740b8ca94 --- /dev/null +++ b/src/test/java/strategy/formation/InitialFormationStrategyTest.java @@ -0,0 +1,6 @@ +package strategy.formation; + + +class InitialFormationStrategyTest { + +} \ No newline at end of file From 47ac21697fcd5a03815cca53e372e95629a16e24 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Thu, 26 Mar 2026 16:29:39 +0900 Subject: [PATCH 09/82] feat : implement InnerFormationStrategy --- src/main/java/.gitkeep | 0 src/main/java/domain/Column.java | 18 ++---- src/main/java/domain/Piece.java | 19 +++++++ src/main/java/domain/PieceType.java | 13 +++++ src/main/java/domain/Position.java | 25 +++++++- src/main/java/domain/Row.java | 20 +++---- src/main/java/domain/TeamColor.java | 6 ++ .../formation/InitialFormationStrategy.java | 10 ++++ .../formation/InnerFormationStrategy.java | 39 +++++++++++++ .../formation/LeftFomrationStrategy.java | 4 ++ .../formation/OuterFomrationStrategy.java | 4 ++ .../formation/RightFomrationStrategy.java | 4 ++ src/test/java/domain/ColumnTest.java | 6 +- src/test/java/domain/RowTest.java | 4 +- .../InitialFormationStrategyTest.java | 6 -- .../formation/InnerFormationStrategyTest.java | 57 +++++++++++++++++++ 16 files changed, 197 insertions(+), 38 deletions(-) delete mode 100644 src/main/java/.gitkeep create mode 100644 src/main/java/domain/Piece.java create mode 100644 src/main/java/domain/PieceType.java create mode 100644 src/main/java/domain/TeamColor.java create mode 100644 src/main/java/strategy/formation/InitialFormationStrategy.java create mode 100644 src/main/java/strategy/formation/InnerFormationStrategy.java create mode 100644 src/main/java/strategy/formation/LeftFomrationStrategy.java create mode 100644 src/main/java/strategy/formation/OuterFomrationStrategy.java create mode 100644 src/main/java/strategy/formation/RightFomrationStrategy.java delete mode 100644 src/test/java/strategy/formation/InitialFormationStrategyTest.java create mode 100644 src/test/java/strategy/formation/InnerFormationStrategyTest.java diff --git a/src/main/java/.gitkeep b/src/main/java/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/main/java/domain/Column.java b/src/main/java/domain/Column.java index 3447651e3f..85879eb1ce 100644 --- a/src/main/java/domain/Column.java +++ b/src/main/java/domain/Column.java @@ -1,21 +1,15 @@ package domain; -public class Column { - private static final int COLUMN_MAX_SIZE = 8; - private final int column; +public record Column(int value) { + private static final int COLUMN_MAX_SIZE = 9; - public Column(int number) { - validateColumn(number); - this.column = number; - } - - public int getValue() { - return this.column; + public Column { + validateColumn(value); } private void validateColumn(int number) { if (number > COLUMN_MAX_SIZE) { - throw new IllegalArgumentException("열의 최대 값은 10입니다."); + throw new IllegalArgumentException("열의 최대 값은 " + COLUMN_MAX_SIZE + "입니다."); } } -} +} \ No newline at end of file diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/Piece.java new file mode 100644 index 0000000000..e43db0cccc --- /dev/null +++ b/src/main/java/domain/Piece.java @@ -0,0 +1,19 @@ +package domain; + +public class Piece { + private TeamColor teamColor; + private PieceType pieceType; + + private Piece(TeamColor teamColor, PieceType pieceType) { + this.teamColor = teamColor; + this.pieceType = pieceType; + } + + public PieceType getPieceType() { + return this.pieceType; + } + + public static Piece of(TeamColor teamColor, PieceType pieceType) { + return new Piece(teamColor,pieceType); + } +} diff --git a/src/main/java/domain/PieceType.java b/src/main/java/domain/PieceType.java new file mode 100644 index 0000000000..a3d9a0cad6 --- /dev/null +++ b/src/main/java/domain/PieceType.java @@ -0,0 +1,13 @@ +package domain; + +public enum PieceType { + CANNON, + ELEPHANT, + GUARD, + HORSE, + KING, + PAWN, + ROOK + + +} diff --git a/src/main/java/domain/Position.java b/src/main/java/domain/Position.java index 543153e776..500cda9eab 100644 --- a/src/main/java/domain/Position.java +++ b/src/main/java/domain/Position.java @@ -1,11 +1,32 @@ package domain; +import java.util.Objects; + public class Position { private final Row row; - private final Column column; - public Position(Row row, Column column) { + private final Column column; + private Position(Row row, Column column) { this.row = row; this.column = column; } + + public static Position of(int row, int column) { + return new Position(new Row(row), new Column(column)); + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) { + return false; + } + Position position = (Position) o; + return Objects.equals(row, position.row) && Objects.equals(column, position.column); + } + + @Override + public int hashCode() { + return Objects.hash(row, column); + } + } diff --git a/src/main/java/domain/Row.java b/src/main/java/domain/Row.java index aa4d2fd6d3..b5ff8730e4 100644 --- a/src/main/java/domain/Row.java +++ b/src/main/java/domain/Row.java @@ -1,21 +1,15 @@ package domain; -public class Row { +public record Row(int value) { private static final int ROW_MAX_SIZE = 8; - private final int row; - public Row(int number) { - validateRow(number); - this.row = number; + public Row { + validateRow(value); } - private void validateRow(int number) { - if (number > ROW_MAX_SIZE) { - throw new IllegalArgumentException("행의 최대 값은 9입니다."); + private void validateRow(int value) { + if (value > ROW_MAX_SIZE) { + throw new IllegalArgumentException("행의 최대 값은 " + ROW_MAX_SIZE + "입니다."); } } - - public int getValue() { - return this.row; - } -} +} \ No newline at end of file diff --git a/src/main/java/domain/TeamColor.java b/src/main/java/domain/TeamColor.java new file mode 100644 index 0000000000..97318428bb --- /dev/null +++ b/src/main/java/domain/TeamColor.java @@ -0,0 +1,6 @@ +package domain; + +public enum TeamColor { + CHO, + HAN +} diff --git a/src/main/java/strategy/formation/InitialFormationStrategy.java b/src/main/java/strategy/formation/InitialFormationStrategy.java new file mode 100644 index 0000000000..c8cc8532a3 --- /dev/null +++ b/src/main/java/strategy/formation/InitialFormationStrategy.java @@ -0,0 +1,10 @@ +package strategy.formation; + +import domain.Piece; +import domain.Position; +import domain.TeamColor; +import java.util.Map; + +public interface InitialFormationStrategy { + Map setupFormation(TeamColor teamColor); +} diff --git a/src/main/java/strategy/formation/InnerFormationStrategy.java b/src/main/java/strategy/formation/InnerFormationStrategy.java new file mode 100644 index 0000000000..1dd426c80e --- /dev/null +++ b/src/main/java/strategy/formation/InnerFormationStrategy.java @@ -0,0 +1,39 @@ +package strategy.formation; + +import domain.Piece; +import domain.PieceType; +import domain.Position; +import domain.TeamColor; +import java.util.HashMap; +import java.util.Map; + +public class InnerFormationStrategy implements InitialFormationStrategy{ + + public Map setupFormation(TeamColor teamColor) { + Map formation = new HashMap<>(); + int y; + if (teamColor.equals(TeamColor.CHO)) { + y =9; + // 왼쪽 마 (x=1) + formation.put(Position.of(1, y), Piece.of(teamColor, PieceType.HORSE)); + // 왼쪽 상 (x=2) + formation.put(Position.of(2, y), Piece.of(teamColor, PieceType.ELEPHANT)); + // 오른쪽 상 (x=6) + formation.put(Position.of(6, y), Piece.of(teamColor, PieceType.ELEPHANT)); + // 오른쪽 마 (x=7) + formation.put(Position.of(7, y), Piece.of(teamColor, PieceType.HORSE)); + return formation; + } + y=0; + // 왼쪽 마 (x=1) + formation.put(Position.of(1, y), Piece.of(teamColor, PieceType.HORSE)); + // 왼쪽 상 (x=2) + formation.put(Position.of(2, y), Piece.of(teamColor, PieceType.ELEPHANT)); + // 오른쪽 상 (x=6) + formation.put(Position.of(6, y), Piece.of(teamColor, PieceType.ELEPHANT)); + // 오른쪽 마 (x=7) + formation.put(Position.of(7, y), Piece.of(teamColor, PieceType.HORSE)); + return formation; + + } +} diff --git a/src/main/java/strategy/formation/LeftFomrationStrategy.java b/src/main/java/strategy/formation/LeftFomrationStrategy.java new file mode 100644 index 0000000000..59550accb6 --- /dev/null +++ b/src/main/java/strategy/formation/LeftFomrationStrategy.java @@ -0,0 +1,4 @@ +package strategy.formation; + +public class LeftFomrationStrategy { +} diff --git a/src/main/java/strategy/formation/OuterFomrationStrategy.java b/src/main/java/strategy/formation/OuterFomrationStrategy.java new file mode 100644 index 0000000000..02231226f6 --- /dev/null +++ b/src/main/java/strategy/formation/OuterFomrationStrategy.java @@ -0,0 +1,4 @@ +package strategy.formation; + +public class OuterFomrationStrategy { +} diff --git a/src/main/java/strategy/formation/RightFomrationStrategy.java b/src/main/java/strategy/formation/RightFomrationStrategy.java new file mode 100644 index 0000000000..d501aae485 --- /dev/null +++ b/src/main/java/strategy/formation/RightFomrationStrategy.java @@ -0,0 +1,4 @@ +package strategy.formation; + +public class RightFomrationStrategy { +} diff --git a/src/test/java/domain/ColumnTest.java b/src/test/java/domain/ColumnTest.java index 66c0072888..e9ce9eb7e0 100644 --- a/src/test/java/domain/ColumnTest.java +++ b/src/test/java/domain/ColumnTest.java @@ -11,10 +11,10 @@ public class ColumnTest { int input = 3; //when - Column row = new Column(input); + Column column = new Column(input); //then - assertThat(row.getValue()).isEqualTo(3); + assertThat(column.value()).isEqualTo(3); } @@ -25,6 +25,6 @@ public class ColumnTest { assertThatThrownBy(() -> new Column(input)) .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("열의 최대 값은 10입니다."); + .hasMessageContaining("열의 최대 값은 9입니다."); } } diff --git a/src/test/java/domain/RowTest.java b/src/test/java/domain/RowTest.java index 7bb81f58c0..4d180df538 100644 --- a/src/test/java/domain/RowTest.java +++ b/src/test/java/domain/RowTest.java @@ -14,7 +14,7 @@ class RowTest { Row row = new Row(input); //then - assertThat(row.getValue()).isEqualTo(3); + assertThat(row.value()).isEqualTo(3); } @@ -25,7 +25,7 @@ class RowTest { assertThatThrownBy(() -> new Row(input)) .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("행의 최대 값은 9입니다."); + .hasMessageContaining("행의 최대 값은 8입니다."); } } \ No newline at end of file diff --git a/src/test/java/strategy/formation/InitialFormationStrategyTest.java b/src/test/java/strategy/formation/InitialFormationStrategyTest.java deleted file mode 100644 index e740b8ca94..0000000000 --- a/src/test/java/strategy/formation/InitialFormationStrategyTest.java +++ /dev/null @@ -1,6 +0,0 @@ -package strategy.formation; - - -class InitialFormationStrategyTest { - -} \ No newline at end of file diff --git a/src/test/java/strategy/formation/InnerFormationStrategyTest.java b/src/test/java/strategy/formation/InnerFormationStrategyTest.java new file mode 100644 index 0000000000..09de8e66a4 --- /dev/null +++ b/src/test/java/strategy/formation/InnerFormationStrategyTest.java @@ -0,0 +1,57 @@ +package strategy.formation; + +import domain.Piece; +import domain.PieceType; +import domain.Position; +import domain.TeamColor; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +public class InnerFormationStrategyTest { + + private InitialFormationStrategy initialFormationStrategy; + + @BeforeEach + public void setUp() { + initialFormationStrategy = new InnerFormationStrategy(); + } + + + @Test + public void 한나라_안상차림일_때_마와_상의_좌표가_올바르다() { + // given & when: 한나라(TeamColor.HAN)의 안상차림 맵을 반환받는다. + Map formation = initialFormationStrategy.setupFormation(TeamColor.HAN); + + // then: 반환된 기물이 정확히 4개인지 확인 + assertThat(formation.size()).isEqualTo(4); + + // 상좌표 검증 - 한상1(2,0), 한상2(6,0) + // (장기판 맨 윗줄이 y=0 이라고 가정) + assertThat(formation.get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(6, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + + // 마좌표 검증 - 한마1(1,0), 한마2(7,0) + assertThat(formation.get(Position.of(1, 0)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(7, 0)).getPieceType()).isEqualTo(PieceType.HORSE); + } + + @Test + public void 초나라_안상차림일_때_마와_상의_좌표가_올바르다() { + // given & when: 초나라(TeamColor.CHO)의 안상차림 맵을 반환받는다. + Map formation = initialFormationStrategy.setupFormation(TeamColor.CHO); + + // then: 반환된 기물이 정확히 4개(마2, 상2)인지 확인 + assertThat(formation.size()).isEqualTo(4); + + // 상좌표 검증 - 초상1(2,9), 초상2(6,9) + // (장기판 맨 아랫줄이 y=9 라고 가정) + assertThat(formation.get(Position.of(2, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(6, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + + // 마좌표 검증 - 초마1(1,9), 초마2(7,9) + assertThat(formation.get(Position.of(7, 9)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(1, 9)).getPieceType()).isEqualTo(PieceType.HORSE); + } +} From 2225189e35b3e3bcd8184519ce1c4458d740be83 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Thu, 26 Mar 2026 16:50:45 +0900 Subject: [PATCH 10/82] feat: implement outer formation strategy --- .../formation/OuterFomrationStrategy.java | 21 +++++++- .../formation/OuterFomrationStrategyTest.java | 50 +++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 src/test/java/strategy/formation/OuterFomrationStrategyTest.java diff --git a/src/main/java/strategy/formation/OuterFomrationStrategy.java b/src/main/java/strategy/formation/OuterFomrationStrategy.java index 02231226f6..8a3f44a789 100644 --- a/src/main/java/strategy/formation/OuterFomrationStrategy.java +++ b/src/main/java/strategy/formation/OuterFomrationStrategy.java @@ -1,4 +1,23 @@ package strategy.formation; -public class OuterFomrationStrategy { +import domain.Piece; +import domain.PieceType; +import domain.Position; +import domain.TeamColor; +import java.util.HashMap; +import java.util.Map; + +public class OuterFomrationStrategy implements InitialFormationStrategy { + + @Override + public Map setupFormation(TeamColor teamColor) { + Map formation = new HashMap<>(); + int y = teamColor == TeamColor.CHO ? 9 : 0; + + formation.put(Position.of(1, y), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(2, y), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(6, y), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(7, y), Piece.of(teamColor, PieceType.ELEPHANT)); + return formation; + } } diff --git a/src/test/java/strategy/formation/OuterFomrationStrategyTest.java b/src/test/java/strategy/formation/OuterFomrationStrategyTest.java new file mode 100644 index 0000000000..01ffd5d897 --- /dev/null +++ b/src/test/java/strategy/formation/OuterFomrationStrategyTest.java @@ -0,0 +1,50 @@ +package strategy.formation; + +import domain.Piece; +import domain.PieceType; +import domain.Position; +import domain.TeamColor; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +public class OuterFomrationStrategyTest { + + private InitialFormationStrategy initialFormationStrategy; + + @BeforeEach + public void setUp() { + initialFormationStrategy = new OuterFomrationStrategy(); + } + + @Test + public void 한나라_바깥상차림일_때_마와_상의_좌표가_올바르다() { + Map formation = initialFormationStrategy.setupFormation(TeamColor.HAN); + + assertThat(formation.size()).isEqualTo(4); + + // 상좌표 검증 - 한상1(1,0), 한상2(7,0) + assertThat(formation.get(Position.of(1, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(7, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + + // 마좌표 검증 - 한마1(2,0), 한마2(6,0) + assertThat(formation.get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(6, 0)).getPieceType()).isEqualTo(PieceType.HORSE); + } + + @Test + public void 초나라_바깥상차림일_때_마와_상의_좌표가_올바르다() { + Map formation = initialFormationStrategy.setupFormation(TeamColor.CHO); + + assertThat(formation.size()).isEqualTo(4); + + // 상좌표 검증 - 초상1(1,9), 초상2(7,9) + assertThat(formation.get(Position.of(1, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(7, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + + // 마좌표 검증 - 초마1(2,9), 초마2(6,9) + assertThat(formation.get(Position.of(2, 9)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(6, 9)).getPieceType()).isEqualTo(PieceType.HORSE); + } +} From 5e84a190123808000ad978b54ddb66eedb548440 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Thu, 26 Mar 2026 16:52:14 +0900 Subject: [PATCH 11/82] feat: implement left formation strategy --- .../formation/LeftFomrationStrategy.java | 21 ++++++++- .../formation/LeftFomrationStrategyTest.java | 43 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/test/java/strategy/formation/LeftFomrationStrategyTest.java diff --git a/src/main/java/strategy/formation/LeftFomrationStrategy.java b/src/main/java/strategy/formation/LeftFomrationStrategy.java index 59550accb6..bf3612069e 100644 --- a/src/main/java/strategy/formation/LeftFomrationStrategy.java +++ b/src/main/java/strategy/formation/LeftFomrationStrategy.java @@ -1,4 +1,23 @@ package strategy.formation; -public class LeftFomrationStrategy { +import domain.Piece; +import domain.PieceType; +import domain.Position; +import domain.TeamColor; +import java.util.HashMap; +import java.util.Map; + +public class LeftFomrationStrategy implements InitialFormationStrategy { + + @Override + public Map setupFormation(TeamColor teamColor) { + Map formation = new HashMap<>(); + int y = teamColor == TeamColor.CHO ? 9 : 0; + + formation.put(Position.of(1, y), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(2, y), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(6, y), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(7, y), Piece.of(teamColor, PieceType.ELEPHANT)); + return formation; + } } diff --git a/src/test/java/strategy/formation/LeftFomrationStrategyTest.java b/src/test/java/strategy/formation/LeftFomrationStrategyTest.java new file mode 100644 index 0000000000..85b54730a3 --- /dev/null +++ b/src/test/java/strategy/formation/LeftFomrationStrategyTest.java @@ -0,0 +1,43 @@ +package strategy.formation; + +import domain.Piece; +import domain.PieceType; +import domain.Position; +import domain.TeamColor; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +public class LeftFomrationStrategyTest { + + private InitialFormationStrategy initialFormationStrategy; + + @BeforeEach + public void setUp() { + initialFormationStrategy = new LeftFomrationStrategy(); + } + + @Test + public void 한나라_좌상차림일_때_마와_상의_좌표가_올바르다() { + Map formation = initialFormationStrategy.setupFormation(TeamColor.HAN); + + assertThat(formation.size()).isEqualTo(4); + assertThat(formation.get(Position.of(1, 0)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(6, 0)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(7, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + } + + @Test + public void 초나라_좌상차림일_때_마와_상의_좌표가_올바르다() { + Map formation = initialFormationStrategy.setupFormation(TeamColor.CHO); + + assertThat(formation.size()).isEqualTo(4); + assertThat(formation.get(Position.of(1, 9)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(2, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(6, 9)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(7, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + } +} From 3c9ee98a6814f0e8914ad336fc1e852215b7906a Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Thu, 26 Mar 2026 16:53:32 +0900 Subject: [PATCH 12/82] feat: implement right formation strategy --- .../formation/RightFomrationStrategy.java | 21 ++++++++- .../formation/RightFomrationStrategyTest.java | 43 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/test/java/strategy/formation/RightFomrationStrategyTest.java diff --git a/src/main/java/strategy/formation/RightFomrationStrategy.java b/src/main/java/strategy/formation/RightFomrationStrategy.java index d501aae485..81ef8eb8ce 100644 --- a/src/main/java/strategy/formation/RightFomrationStrategy.java +++ b/src/main/java/strategy/formation/RightFomrationStrategy.java @@ -1,4 +1,23 @@ package strategy.formation; -public class RightFomrationStrategy { +import domain.Piece; +import domain.PieceType; +import domain.Position; +import domain.TeamColor; +import java.util.HashMap; +import java.util.Map; + +public class RightFomrationStrategy implements InitialFormationStrategy { + + @Override + public Map setupFormation(TeamColor teamColor) { + Map formation = new HashMap<>(); + int y = teamColor == TeamColor.CHO ? 9 : 0; + + formation.put(Position.of(1, y), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(2, y), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(6, y), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(7, y), Piece.of(teamColor, PieceType.HORSE)); + return formation; + } } diff --git a/src/test/java/strategy/formation/RightFomrationStrategyTest.java b/src/test/java/strategy/formation/RightFomrationStrategyTest.java new file mode 100644 index 0000000000..222dfdd54c --- /dev/null +++ b/src/test/java/strategy/formation/RightFomrationStrategyTest.java @@ -0,0 +1,43 @@ +package strategy.formation; + +import domain.Piece; +import domain.PieceType; +import domain.Position; +import domain.TeamColor; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +public class RightFomrationStrategyTest { + + private InitialFormationStrategy initialFormationStrategy; + + @BeforeEach + public void setUp() { + initialFormationStrategy = new RightFomrationStrategy(); + } + + @Test + public void 한나라_우상차림일_때_마와_상의_좌표가_올바르다() { + Map formation = initialFormationStrategy.setupFormation(TeamColor.HAN); + + assertThat(formation.size()).isEqualTo(4); + assertThat(formation.get(Position.of(1, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(6, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(7, 0)).getPieceType()).isEqualTo(PieceType.HORSE); + } + + @Test + public void 초나라_우상차림일_때_마와_상의_좌표가_올바르다() { + Map formation = initialFormationStrategy.setupFormation(TeamColor.CHO); + + assertThat(formation.size()).isEqualTo(4); + assertThat(formation.get(Position.of(1, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(2, 9)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(6, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(7, 9)).getPieceType()).isEqualTo(PieceType.HORSE); + } +} From 3bb207b6b0cf36bc3ed38d26fcf728c9a555da01 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Thu, 26 Mar 2026 17:00:28 +0900 Subject: [PATCH 13/82] refactor: rename FormationStrategy --- ...{LeftFomrationStrategy.java => LeftFormationStrategy.java} | 2 +- ...uterFomrationStrategy.java => OuterFormationStrategy.java} | 2 +- ...ightFomrationStrategy.java => RightFormationStrategy.java} | 2 +- ...rationStrategyTest.java => LeftFormationStrategyTest.java} | 4 ++-- ...ationStrategyTest.java => OuterFormationStrategyTest.java} | 4 ++-- ...ationStrategyTest.java => RightFormationStrategyTest.java} | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) rename src/main/java/strategy/formation/{LeftFomrationStrategy.java => LeftFormationStrategy.java} (92%) rename src/main/java/strategy/formation/{OuterFomrationStrategy.java => OuterFormationStrategy.java} (92%) rename src/main/java/strategy/formation/{RightFomrationStrategy.java => RightFormationStrategy.java} (92%) rename src/test/java/strategy/formation/{LeftFomrationStrategyTest.java => LeftFormationStrategyTest.java} (94%) rename src/test/java/strategy/formation/{OuterFomrationStrategyTest.java => OuterFormationStrategyTest.java} (94%) rename src/test/java/strategy/formation/{RightFomrationStrategyTest.java => RightFormationStrategyTest.java} (94%) diff --git a/src/main/java/strategy/formation/LeftFomrationStrategy.java b/src/main/java/strategy/formation/LeftFormationStrategy.java similarity index 92% rename from src/main/java/strategy/formation/LeftFomrationStrategy.java rename to src/main/java/strategy/formation/LeftFormationStrategy.java index bf3612069e..d4e222a726 100644 --- a/src/main/java/strategy/formation/LeftFomrationStrategy.java +++ b/src/main/java/strategy/formation/LeftFormationStrategy.java @@ -7,7 +7,7 @@ import java.util.HashMap; import java.util.Map; -public class LeftFomrationStrategy implements InitialFormationStrategy { +public class LeftFormationStrategy implements InitialFormationStrategy { @Override public Map setupFormation(TeamColor teamColor) { diff --git a/src/main/java/strategy/formation/OuterFomrationStrategy.java b/src/main/java/strategy/formation/OuterFormationStrategy.java similarity index 92% rename from src/main/java/strategy/formation/OuterFomrationStrategy.java rename to src/main/java/strategy/formation/OuterFormationStrategy.java index 8a3f44a789..6c755f0173 100644 --- a/src/main/java/strategy/formation/OuterFomrationStrategy.java +++ b/src/main/java/strategy/formation/OuterFormationStrategy.java @@ -7,7 +7,7 @@ import java.util.HashMap; import java.util.Map; -public class OuterFomrationStrategy implements InitialFormationStrategy { +public class OuterFormationStrategy implements InitialFormationStrategy { @Override public Map setupFormation(TeamColor teamColor) { diff --git a/src/main/java/strategy/formation/RightFomrationStrategy.java b/src/main/java/strategy/formation/RightFormationStrategy.java similarity index 92% rename from src/main/java/strategy/formation/RightFomrationStrategy.java rename to src/main/java/strategy/formation/RightFormationStrategy.java index 81ef8eb8ce..b45e0a53f5 100644 --- a/src/main/java/strategy/formation/RightFomrationStrategy.java +++ b/src/main/java/strategy/formation/RightFormationStrategy.java @@ -7,7 +7,7 @@ import java.util.HashMap; import java.util.Map; -public class RightFomrationStrategy implements InitialFormationStrategy { +public class RightFormationStrategy implements InitialFormationStrategy { @Override public Map setupFormation(TeamColor teamColor) { diff --git a/src/test/java/strategy/formation/LeftFomrationStrategyTest.java b/src/test/java/strategy/formation/LeftFormationStrategyTest.java similarity index 94% rename from src/test/java/strategy/formation/LeftFomrationStrategyTest.java rename to src/test/java/strategy/formation/LeftFormationStrategyTest.java index 85b54730a3..698ebb12ba 100644 --- a/src/test/java/strategy/formation/LeftFomrationStrategyTest.java +++ b/src/test/java/strategy/formation/LeftFormationStrategyTest.java @@ -10,13 +10,13 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -public class LeftFomrationStrategyTest { +public class LeftFormationStrategyTest { private InitialFormationStrategy initialFormationStrategy; @BeforeEach public void setUp() { - initialFormationStrategy = new LeftFomrationStrategy(); + initialFormationStrategy = new LeftFormationStrategy(); } @Test diff --git a/src/test/java/strategy/formation/OuterFomrationStrategyTest.java b/src/test/java/strategy/formation/OuterFormationStrategyTest.java similarity index 94% rename from src/test/java/strategy/formation/OuterFomrationStrategyTest.java rename to src/test/java/strategy/formation/OuterFormationStrategyTest.java index 01ffd5d897..d5c6af6f53 100644 --- a/src/test/java/strategy/formation/OuterFomrationStrategyTest.java +++ b/src/test/java/strategy/formation/OuterFormationStrategyTest.java @@ -9,13 +9,13 @@ import org.junit.jupiter.api.Test; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -public class OuterFomrationStrategyTest { +public class OuterFormationStrategyTest { private InitialFormationStrategy initialFormationStrategy; @BeforeEach public void setUp() { - initialFormationStrategy = new OuterFomrationStrategy(); + initialFormationStrategy = new OuterFormationStrategy(); } @Test diff --git a/src/test/java/strategy/formation/RightFomrationStrategyTest.java b/src/test/java/strategy/formation/RightFormationStrategyTest.java similarity index 94% rename from src/test/java/strategy/formation/RightFomrationStrategyTest.java rename to src/test/java/strategy/formation/RightFormationStrategyTest.java index 222dfdd54c..1e101cc678 100644 --- a/src/test/java/strategy/formation/RightFomrationStrategyTest.java +++ b/src/test/java/strategy/formation/RightFormationStrategyTest.java @@ -10,13 +10,13 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -public class RightFomrationStrategyTest { +public class RightFormationStrategyTest { private InitialFormationStrategy initialFormationStrategy; @BeforeEach public void setUp() { - initialFormationStrategy = new RightFomrationStrategy(); + initialFormationStrategy = new RightFormationStrategy(); } @Test From 19e5a8b9657e41de6b8fb100b4f4daefa52e257d Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Thu, 26 Mar 2026 17:36:51 +0900 Subject: [PATCH 14/82] feat : add fixed piece's formation setup function for InitialFormationStrategy --- .../formation/InitialFormationStrategy.java | 36 +++++++++ .../InitialFormationStrategyTest.java | 81 +++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 src/test/java/strategy/formation/InitialFormationStrategyTest.java diff --git a/src/main/java/strategy/formation/InitialFormationStrategy.java b/src/main/java/strategy/formation/InitialFormationStrategy.java index c8cc8532a3..afad21d921 100644 --- a/src/main/java/strategy/formation/InitialFormationStrategy.java +++ b/src/main/java/strategy/formation/InitialFormationStrategy.java @@ -1,10 +1,46 @@ package strategy.formation; import domain.Piece; +import domain.PieceType; import domain.Position; import domain.TeamColor; +import java.util.HashMap; import java.util.Map; public interface InitialFormationStrategy { + Map setupFormation(TeamColor teamColor); + + default Map placeFixedPieces(TeamColor teamColor) { + if (teamColor == TeamColor.HAN) { + return createFixedMap(teamColor, 0, 1, 2, 3); + } + return createFixedMap(teamColor, 9, 8, 7, 6); + } + + private Map createFixedMap(TeamColor teamColor, int backRankY, int kingY, int cannonY, int pawnY) { + Map map = new HashMap<>(); + + // 1. 차 (ROOK) - 양쪽 맨 끝 (x = 0, 8) + map.put(Position.of(0, backRankY), Piece.of(teamColor, PieceType.ROOK)); + map.put(Position.of(8, backRankY), Piece.of(teamColor, PieceType.ROOK)); + + // 2. 사 (GUARD) - 궁성 안쪽 귀 (x = 3, 5) + map.put(Position.of(3, backRankY), Piece.of(teamColor, PieceType.GUARD)); + map.put(Position.of(5, backRankY), Piece.of(teamColor, PieceType.GUARD)); + + // 3. 왕 (KING) - 궁성 중앙 (x = 4) + map.put(Position.of(4, kingY), Piece.of(teamColor, PieceType.KING)); + + // 4. 포 (CANNON) - (x = 1, 7) + map.put(Position.of(1, cannonY), Piece.of(teamColor, PieceType.CANNON)); + map.put(Position.of(7, cannonY), Piece.of(teamColor, PieceType.CANNON)); + + // 5. 졸/병 (PAWN) - 5개 (x = 0, 2, 4, 6, 8) + for (int x = 0; x <= 8; x += 2) { + map.put(Position.of(x, pawnY), Piece.of(teamColor, PieceType.PAWN)); + } + + return map; + } } diff --git a/src/test/java/strategy/formation/InitialFormationStrategyTest.java b/src/test/java/strategy/formation/InitialFormationStrategyTest.java new file mode 100644 index 0000000000..f3cfcfc059 --- /dev/null +++ b/src/test/java/strategy/formation/InitialFormationStrategyTest.java @@ -0,0 +1,81 @@ +package strategy.formation; + +import domain.Piece; +import domain.PieceType; +import domain.Position; +import domain.TeamColor; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class InitialFormationStrategyTest { + + private InitialFormationStrategy strategy; + + @BeforeEach + void setUp() { + strategy = new TestStrategy(); + } + + @Test + void 한나라_고정_기물들이_올바른_위치에_배치된다() { + Map result = strategy.placeFixedPieces(TeamColor.HAN); + + // 한나라는 위쪽 진영 (y = 0 ~ 3) + // 1. 차 + assertThat(result.get(Position.of(0, 0)).getPieceType()).isEqualTo(PieceType.ROOK); + assertThat(result.get(Position.of(8, 0)).getPieceType()).isEqualTo(PieceType.ROOK); + + // 2. 사 + assertThat(result.get(Position.of(3, 0)).getPieceType()).isEqualTo(PieceType.GUARD); + assertThat(result.get(Position.of(5, 0)).getPieceType()).isEqualTo(PieceType.GUARD); + + // 3. 궁 + assertThat(result.get(Position.of(4, 1)).getPieceType()).isEqualTo(PieceType.KING); + + // 4. 포 + assertThat(result.get(Position.of(1, 2)).getPieceType()).isEqualTo(PieceType.CANNON); + assertThat(result.get(Position.of(7, 2)).getPieceType()).isEqualTo(PieceType.CANNON); + + // 5. 병 + assertThat(result.get(Position.of(0, 3)).getPieceType()).isEqualTo(PieceType.PAWN); + assertThat(result.get(Position.of(4, 3)).getPieceType()).isEqualTo(PieceType.PAWN); + assertThat(result.get(Position.of(8, 3)).getPieceType()).isEqualTo(PieceType.PAWN); + } + + @Test + void 초나라_고정_기물들이_올바른_위치에_배치된다() { + Map result = strategy.placeFixedPieces(TeamColor.CHO); + + // 초나라는 아래쪽 진영 (y = 6 ~ 9) + // 1. 차 + assertThat(result.get(Position.of(0, 9)).getPieceType()).isEqualTo(PieceType.ROOK); + assertThat(result.get(Position.of(8, 9)).getPieceType()).isEqualTo(PieceType.ROOK); + + // 2. 사 + assertThat(result.get(Position.of(3, 9)).getPieceType()).isEqualTo(PieceType.GUARD); + assertThat(result.get(Position.of(5, 9)).getPieceType()).isEqualTo(PieceType.GUARD); + + // 3. 궁 + assertThat(result.get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); + + // 4. 포 + assertThat(result.get(Position.of(1, 7)).getPieceType()).isEqualTo(PieceType.CANNON); + assertThat(result.get(Position.of(7, 7)).getPieceType()).isEqualTo(PieceType.CANNON); + + // 5. 졸 + assertThat(result.get(Position.of(0, 6)).getPieceType()).isEqualTo(PieceType.PAWN); + assertThat(result.get(Position.of(4, 6)).getPieceType()).isEqualTo(PieceType.PAWN); + assertThat(result.get(Position.of(8, 6)).getPieceType()).isEqualTo(PieceType.PAWN); + } +} + +class TestStrategy implements InitialFormationStrategy { + @Override + public Map setupFormation(TeamColor teamColor) { + return Map.of(); + } +} \ No newline at end of file From 28a8271e77e12b90feec875ae4e5e2ecfd10072f Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Thu, 26 Mar 2026 18:11:09 +0900 Subject: [PATCH 15/82] test : create Initializer Test Code --- src/test/java/InitializerTest.java | 85 ++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 src/test/java/InitializerTest.java diff --git a/src/test/java/InitializerTest.java b/src/test/java/InitializerTest.java new file mode 100644 index 0000000000..e255e6ac79 --- /dev/null +++ b/src/test/java/InitializerTest.java @@ -0,0 +1,85 @@ +import domain.InitialGameState; +import domain.PieceType; +import domain.Position; + +import domain.TeamColor; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + + + +import static org.assertj.core.api.Assertions.assertThat; +import strategy.formation.InitialFormationStrategy; +import strategy.formation.InnerFormationStrategy; + +class InitializerTest { + + InitialFormationStrategy choStrategy; + InitialFormationStrategy hanStrategy; + InitialGameState initialGameState; + + @BeforeEach + public void setUp(){ + choStrategy = new InnerFormationStrategy(); + hanStrategy = new InnerFormationStrategy(); + Initializer initializer = new Initializer(choStrategy, hanStrategy); + initialGameState = initializer.initialize(); + } + + + @Test + void 초나라_한나라_전략을_주입받아_총_32개의_기물이_세팅된_초기_장기판을_반환한다() { + assertThat(initialGameState.boardState()).hasSize(32); + assertThat(initialGameState.boardState().get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); + assertThat(initialGameState.boardState().get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + } + + @Test + void 초나라_기물_리스트를_생성한다() { + // 16개 생성됐는지 + assertThat(initialGameState.choPieces()).hasSize(16); + // 기물 마다 개수를 테스트 : 졸5, 상2, 마2, 포2, 차2, 사2, 궁1 + assertThat( + initialGameState.choPieces().stream() + .filter(p -> p.getTeamColor() == TeamColor.CHO) + .filter(p -> p.getPieceType() == PieceType.ELEPHANT) + ).hasSize(2); + + assertThat( + initialGameState.choPieces().stream() + .filter(p -> p.getTeamColor() == TeamColor.CHO) + .filter(p -> p.getPieceType() == PieceType.HORSE) + ).hasSize(2); + + assertThat( + initialGameState.choPieces().stream() + .filter(p -> p.getTeamColor() == TeamColor.CHO) + .filter(p -> p.getPieceType() == PieceType.CANNON) + ).hasSize(2); + + assertThat( + initialGameState.choPieces().stream() + .filter(p -> p.getTeamColor() == TeamColor.CHO) + .filter(p -> p.getPieceType() == PieceType.ROOK) + ).hasSize(2); + + assertThat( + initialGameState.choPieces().stream() + .filter(p -> p.getTeamColor() == TeamColor.CHO) + .filter(p -> p.getPieceType() == PieceType.GUARD) + ).hasSize(2); + + assertThat( + initialGameState.choPieces().stream() + .filter(p -> p.getTeamColor() == TeamColor.CHO) + .filter(p -> p.getPieceType() == PieceType.PAWN) + ).hasSize(5); + + assertThat( + initialGameState.choPieces().stream() + .filter(p -> p.getTeamColor() == TeamColor.CHO) + .filter(p -> p.getPieceType() == PieceType.KING) + ).hasSize(1); + + } +} \ No newline at end of file From 17e78ab5d42db0a80fe5b3862fae4c861bf8e464 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Thu, 26 Mar 2026 18:13:16 +0900 Subject: [PATCH 16/82] feat : implement Initailizer and Piece feature --- src/main/java/Initializer.java | 37 +++++++++++++++++++++++++++++++++ src/main/java/domain/Piece.java | 4 ++++ 2 files changed, 41 insertions(+) create mode 100644 src/main/java/Initializer.java diff --git a/src/main/java/Initializer.java b/src/main/java/Initializer.java new file mode 100644 index 0000000000..cea3517590 --- /dev/null +++ b/src/main/java/Initializer.java @@ -0,0 +1,37 @@ +import domain.InitialGameState; +import domain.Piece; +import domain.Position; +import domain.TeamColor; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import strategy.formation.InitialFormationStrategy; + +public class Initializer { + + private InitialFormationStrategy choStrategy; + private InitialFormationStrategy hanStrategy; + + public Initializer(InitialFormationStrategy choStrategy, InitialFormationStrategy hanStrategy) { + this.choStrategy = choStrategy; + this.hanStrategy = hanStrategy; + } + + public InitialGameState initialize() { + Map board = new HashMap<>(); + board.putAll(choStrategy.placeFixedPieces(TeamColor.CHO)); + board.putAll(choStrategy.setupFormation(TeamColor.CHO)); + board.putAll(hanStrategy.placeFixedPieces(TeamColor.HAN)); + board.putAll(choStrategy.setupFormation(TeamColor.HAN)); + + List choPieces = board.values().stream() + .filter(piece -> piece.getTeamColor() == TeamColor.CHO) + .toList(); + + List hanPieces = board.values().stream() + .filter(piece -> piece.getTeamColor() == TeamColor.HAN) + .toList(); + + return new InitialGameState(board, choPieces, hanPieces); + } +} diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/Piece.java index e43db0cccc..ca14ba8589 100644 --- a/src/main/java/domain/Piece.java +++ b/src/main/java/domain/Piece.java @@ -13,6 +13,10 @@ public PieceType getPieceType() { return this.pieceType; } + public TeamColor getTeamColor() { + return this.teamColor; + } + public static Piece of(TeamColor teamColor, PieceType pieceType) { return new Piece(teamColor,pieceType); } From 18bd9dafd93103c9cda4c2bcede1c57d221438b3 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Thu, 26 Mar 2026 19:50:09 +0900 Subject: [PATCH 17/82] refactor: wrapping FixedPieces and Formation method --- .../formation/InitialFormationStrategy.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/main/java/strategy/formation/InitialFormationStrategy.java b/src/main/java/strategy/formation/InitialFormationStrategy.java index afad21d921..a56a047092 100644 --- a/src/main/java/strategy/formation/InitialFormationStrategy.java +++ b/src/main/java/strategy/formation/InitialFormationStrategy.java @@ -7,11 +7,23 @@ import java.util.HashMap; import java.util.Map; -public interface InitialFormationStrategy { +public abstract class InitialFormationStrategy { - Map setupFormation(TeamColor teamColor); + public final Map setUpPieces(TeamColor teamColor) { - default Map placeFixedPieces(TeamColor teamColor) { + Map formationPieces = setupFormation(teamColor); + Map fixedPieces = placeFixedPieces(teamColor); + Map allPieces = new HashMap<>(); + + allPieces.putAll(formationPieces); + allPieces.putAll(fixedPieces); + + return allPieces; + } + + protected abstract Map setupFormation(TeamColor teamColor); + + private Map placeFixedPieces(TeamColor teamColor) { if (teamColor == TeamColor.HAN) { return createFixedMap(teamColor, 0, 1, 2, 3); } From 4c654a0a39eafc57f2b50e174389056f37612c2d Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Thu, 26 Mar 2026 20:32:27 +0900 Subject: [PATCH 18/82] =?UTF-8?q?refactor:=20=EC=9D=B4=EB=8B=88=EC=85=9C?= =?UTF-8?q?=EB=9D=BC=EC=9D=B4=EC=A0=80=20=EB=8F=99=EC=9E=91=20setUpPieces?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EC=BA=A1=EC=8A=90?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Initializer.java | 6 ++---- .../formation/InnerFormationStrategy.java | 5 +++-- .../formation/LeftFormationStrategy.java | 4 ++-- .../formation/OuterFormationStrategy.java | 4 ++-- .../formation/RightFormationStrategy.java | 4 ++-- .../InitialFormationStrategyTest.java | 14 +++++++++----- .../formation/InnerFormationStrategyTest.java | 18 ++++++++++-------- .../formation/LeftFormationStrategyTest.java | 10 ++++++---- .../formation/OuterFormationStrategyTest.java | 10 ++++++---- .../formation/RightFormationStrategyTest.java | 10 ++++++---- 10 files changed, 48 insertions(+), 37 deletions(-) diff --git a/src/main/java/Initializer.java b/src/main/java/Initializer.java index cea3517590..1aee87a40f 100644 --- a/src/main/java/Initializer.java +++ b/src/main/java/Initializer.java @@ -19,10 +19,8 @@ public Initializer(InitialFormationStrategy choStrategy, InitialFormationStrateg public InitialGameState initialize() { Map board = new HashMap<>(); - board.putAll(choStrategy.placeFixedPieces(TeamColor.CHO)); - board.putAll(choStrategy.setupFormation(TeamColor.CHO)); - board.putAll(hanStrategy.placeFixedPieces(TeamColor.HAN)); - board.putAll(choStrategy.setupFormation(TeamColor.HAN)); + board.putAll(choStrategy.setUpPieces(TeamColor.CHO)); + board.putAll(hanStrategy.setUpPieces(TeamColor.HAN)); List choPieces = board.values().stream() .filter(piece -> piece.getTeamColor() == TeamColor.CHO) diff --git a/src/main/java/strategy/formation/InnerFormationStrategy.java b/src/main/java/strategy/formation/InnerFormationStrategy.java index 1dd426c80e..4de513f819 100644 --- a/src/main/java/strategy/formation/InnerFormationStrategy.java +++ b/src/main/java/strategy/formation/InnerFormationStrategy.java @@ -7,9 +7,10 @@ import java.util.HashMap; import java.util.Map; -public class InnerFormationStrategy implements InitialFormationStrategy{ +public class InnerFormationStrategy extends InitialFormationStrategy { - public Map setupFormation(TeamColor teamColor) { + @Override + protected Map setupFormation(TeamColor teamColor) { Map formation = new HashMap<>(); int y; if (teamColor.equals(TeamColor.CHO)) { diff --git a/src/main/java/strategy/formation/LeftFormationStrategy.java b/src/main/java/strategy/formation/LeftFormationStrategy.java index d4e222a726..05473ba70b 100644 --- a/src/main/java/strategy/formation/LeftFormationStrategy.java +++ b/src/main/java/strategy/formation/LeftFormationStrategy.java @@ -7,10 +7,10 @@ import java.util.HashMap; import java.util.Map; -public class LeftFormationStrategy implements InitialFormationStrategy { +public class LeftFormationStrategy extends InitialFormationStrategy { @Override - public Map setupFormation(TeamColor teamColor) { + protected Map setupFormation(TeamColor teamColor) { Map formation = new HashMap<>(); int y = teamColor == TeamColor.CHO ? 9 : 0; diff --git a/src/main/java/strategy/formation/OuterFormationStrategy.java b/src/main/java/strategy/formation/OuterFormationStrategy.java index 6c755f0173..b718f09c73 100644 --- a/src/main/java/strategy/formation/OuterFormationStrategy.java +++ b/src/main/java/strategy/formation/OuterFormationStrategy.java @@ -7,10 +7,10 @@ import java.util.HashMap; import java.util.Map; -public class OuterFormationStrategy implements InitialFormationStrategy { +public class OuterFormationStrategy extends InitialFormationStrategy { @Override - public Map setupFormation(TeamColor teamColor) { + protected Map setupFormation(TeamColor teamColor) { Map formation = new HashMap<>(); int y = teamColor == TeamColor.CHO ? 9 : 0; diff --git a/src/main/java/strategy/formation/RightFormationStrategy.java b/src/main/java/strategy/formation/RightFormationStrategy.java index b45e0a53f5..74a05ac155 100644 --- a/src/main/java/strategy/formation/RightFormationStrategy.java +++ b/src/main/java/strategy/formation/RightFormationStrategy.java @@ -7,10 +7,10 @@ import java.util.HashMap; import java.util.Map; -public class RightFormationStrategy implements InitialFormationStrategy { +public class RightFormationStrategy extends InitialFormationStrategy { @Override - public Map setupFormation(TeamColor teamColor) { + protected Map setupFormation(TeamColor teamColor) { Map formation = new HashMap<>(); int y = teamColor == TeamColor.CHO ? 9 : 0; diff --git a/src/test/java/strategy/formation/InitialFormationStrategyTest.java b/src/test/java/strategy/formation/InitialFormationStrategyTest.java index f3cfcfc059..916d8c6406 100644 --- a/src/test/java/strategy/formation/InitialFormationStrategyTest.java +++ b/src/test/java/strategy/formation/InitialFormationStrategyTest.java @@ -22,7 +22,9 @@ void setUp() { @Test void 한나라_고정_기물들이_올바른_위치에_배치된다() { - Map result = strategy.placeFixedPieces(TeamColor.HAN); + Map result = strategy.setUpPieces(TeamColor.HAN); + + assertThat(result).hasSize(12); // 한나라는 위쪽 진영 (y = 0 ~ 3) // 1. 차 @@ -48,7 +50,9 @@ void setUp() { @Test void 초나라_고정_기물들이_올바른_위치에_배치된다() { - Map result = strategy.placeFixedPieces(TeamColor.CHO); + Map result = strategy.setUpPieces(TeamColor.CHO); + + assertThat(result).hasSize(12); // 초나라는 아래쪽 진영 (y = 6 ~ 9) // 1. 차 @@ -73,9 +77,9 @@ void setUp() { } } -class TestStrategy implements InitialFormationStrategy { +class TestStrategy extends InitialFormationStrategy { @Override - public Map setupFormation(TeamColor teamColor) { + protected Map setupFormation(TeamColor teamColor) { return Map.of(); } -} \ No newline at end of file +} diff --git a/src/test/java/strategy/formation/InnerFormationStrategyTest.java b/src/test/java/strategy/formation/InnerFormationStrategyTest.java index 09de8e66a4..cd89e495e6 100644 --- a/src/test/java/strategy/formation/InnerFormationStrategyTest.java +++ b/src/test/java/strategy/formation/InnerFormationStrategyTest.java @@ -21,11 +21,11 @@ public void setUp() { @Test public void 한나라_안상차림일_때_마와_상의_좌표가_올바르다() { - // given & when: 한나라(TeamColor.HAN)의 안상차림 맵을 반환받는다. - Map formation = initialFormationStrategy.setupFormation(TeamColor.HAN); + // given & when: 한나라(TeamColor.HAN)의 전체 초기 배치 맵을 반환받는다. + Map formation = initialFormationStrategy.setUpPieces(TeamColor.HAN); - // then: 반환된 기물이 정확히 4개인지 확인 - assertThat(formation.size()).isEqualTo(4); + // then: 반환된 기물이 정확히 16개인지 확인 + assertThat(formation.size()).isEqualTo(16); // 상좌표 검증 - 한상1(2,0), 한상2(6,0) // (장기판 맨 윗줄이 y=0 이라고 가정) @@ -35,15 +35,16 @@ public void setUp() { // 마좌표 검증 - 한마1(1,0), 한마2(7,0) assertThat(formation.get(Position.of(1, 0)).getPieceType()).isEqualTo(PieceType.HORSE); assertThat(formation.get(Position.of(7, 0)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(4, 1)).getPieceType()).isEqualTo(PieceType.KING); } @Test public void 초나라_안상차림일_때_마와_상의_좌표가_올바르다() { - // given & when: 초나라(TeamColor.CHO)의 안상차림 맵을 반환받는다. - Map formation = initialFormationStrategy.setupFormation(TeamColor.CHO); + // given & when: 초나라(TeamColor.CHO)의 전체 초기 배치 맵을 반환받는다. + Map formation = initialFormationStrategy.setUpPieces(TeamColor.CHO); - // then: 반환된 기물이 정확히 4개(마2, 상2)인지 확인 - assertThat(formation.size()).isEqualTo(4); + // then: 반환된 기물이 정확히 16개인지 확인 + assertThat(formation.size()).isEqualTo(16); // 상좌표 검증 - 초상1(2,9), 초상2(6,9) // (장기판 맨 아랫줄이 y=9 라고 가정) @@ -53,5 +54,6 @@ public void setUp() { // 마좌표 검증 - 초마1(1,9), 초마2(7,9) assertThat(formation.get(Position.of(7, 9)).getPieceType()).isEqualTo(PieceType.HORSE); assertThat(formation.get(Position.of(1, 9)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); } } diff --git a/src/test/java/strategy/formation/LeftFormationStrategyTest.java b/src/test/java/strategy/formation/LeftFormationStrategyTest.java index 698ebb12ba..be8108532a 100644 --- a/src/test/java/strategy/formation/LeftFormationStrategyTest.java +++ b/src/test/java/strategy/formation/LeftFormationStrategyTest.java @@ -21,23 +21,25 @@ public void setUp() { @Test public void 한나라_좌상차림일_때_마와_상의_좌표가_올바르다() { - Map formation = initialFormationStrategy.setupFormation(TeamColor.HAN); + Map formation = initialFormationStrategy.setUpPieces(TeamColor.HAN); - assertThat(formation.size()).isEqualTo(4); + assertThat(formation.size()).isEqualTo(16); assertThat(formation.get(Position.of(1, 0)).getPieceType()).isEqualTo(PieceType.HORSE); assertThat(formation.get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); assertThat(formation.get(Position.of(6, 0)).getPieceType()).isEqualTo(PieceType.HORSE); assertThat(formation.get(Position.of(7, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(4, 1)).getPieceType()).isEqualTo(PieceType.KING); } @Test public void 초나라_좌상차림일_때_마와_상의_좌표가_올바르다() { - Map formation = initialFormationStrategy.setupFormation(TeamColor.CHO); + Map formation = initialFormationStrategy.setUpPieces(TeamColor.CHO); - assertThat(formation.size()).isEqualTo(4); + assertThat(formation.size()).isEqualTo(16); assertThat(formation.get(Position.of(1, 9)).getPieceType()).isEqualTo(PieceType.HORSE); assertThat(formation.get(Position.of(2, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); assertThat(formation.get(Position.of(6, 9)).getPieceType()).isEqualTo(PieceType.HORSE); assertThat(formation.get(Position.of(7, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); } } diff --git a/src/test/java/strategy/formation/OuterFormationStrategyTest.java b/src/test/java/strategy/formation/OuterFormationStrategyTest.java index d5c6af6f53..43c2cdd46c 100644 --- a/src/test/java/strategy/formation/OuterFormationStrategyTest.java +++ b/src/test/java/strategy/formation/OuterFormationStrategyTest.java @@ -20,9 +20,9 @@ public void setUp() { @Test public void 한나라_바깥상차림일_때_마와_상의_좌표가_올바르다() { - Map formation = initialFormationStrategy.setupFormation(TeamColor.HAN); + Map formation = initialFormationStrategy.setUpPieces(TeamColor.HAN); - assertThat(formation.size()).isEqualTo(4); + assertThat(formation.size()).isEqualTo(16); // 상좌표 검증 - 한상1(1,0), 한상2(7,0) assertThat(formation.get(Position.of(1, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); @@ -31,13 +31,14 @@ public void setUp() { // 마좌표 검증 - 한마1(2,0), 한마2(6,0) assertThat(formation.get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.HORSE); assertThat(formation.get(Position.of(6, 0)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(4, 1)).getPieceType()).isEqualTo(PieceType.KING); } @Test public void 초나라_바깥상차림일_때_마와_상의_좌표가_올바르다() { - Map formation = initialFormationStrategy.setupFormation(TeamColor.CHO); + Map formation = initialFormationStrategy.setUpPieces(TeamColor.CHO); - assertThat(formation.size()).isEqualTo(4); + assertThat(formation.size()).isEqualTo(16); // 상좌표 검증 - 초상1(1,9), 초상2(7,9) assertThat(formation.get(Position.of(1, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); @@ -46,5 +47,6 @@ public void setUp() { // 마좌표 검증 - 초마1(2,9), 초마2(6,9) assertThat(formation.get(Position.of(2, 9)).getPieceType()).isEqualTo(PieceType.HORSE); assertThat(formation.get(Position.of(6, 9)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); } } diff --git a/src/test/java/strategy/formation/RightFormationStrategyTest.java b/src/test/java/strategy/formation/RightFormationStrategyTest.java index 1e101cc678..5242949504 100644 --- a/src/test/java/strategy/formation/RightFormationStrategyTest.java +++ b/src/test/java/strategy/formation/RightFormationStrategyTest.java @@ -21,23 +21,25 @@ public void setUp() { @Test public void 한나라_우상차림일_때_마와_상의_좌표가_올바르다() { - Map formation = initialFormationStrategy.setupFormation(TeamColor.HAN); + Map formation = initialFormationStrategy.setUpPieces(TeamColor.HAN); - assertThat(formation.size()).isEqualTo(4); + assertThat(formation.size()).isEqualTo(16); assertThat(formation.get(Position.of(1, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); assertThat(formation.get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.HORSE); assertThat(formation.get(Position.of(6, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); assertThat(formation.get(Position.of(7, 0)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(4, 1)).getPieceType()).isEqualTo(PieceType.KING); } @Test public void 초나라_우상차림일_때_마와_상의_좌표가_올바르다() { - Map formation = initialFormationStrategy.setupFormation(TeamColor.CHO); + Map formation = initialFormationStrategy.setUpPieces(TeamColor.CHO); - assertThat(formation.size()).isEqualTo(4); + assertThat(formation.size()).isEqualTo(16); assertThat(formation.get(Position.of(1, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); assertThat(formation.get(Position.of(2, 9)).getPieceType()).isEqualTo(PieceType.HORSE); assertThat(formation.get(Position.of(6, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); assertThat(formation.get(Position.of(7, 9)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); } } From 6482ce86c7a955a421442c4b4fdba4c7bacc77e5 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Thu, 26 Mar 2026 20:33:46 +0900 Subject: [PATCH 19/82] test: add PieceStorage test code --- src/test/java/domain/PieceStorageTest.java | 35 ++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/test/java/domain/PieceStorageTest.java diff --git a/src/test/java/domain/PieceStorageTest.java b/src/test/java/domain/PieceStorageTest.java new file mode 100644 index 0000000000..046abf04bf --- /dev/null +++ b/src/test/java/domain/PieceStorageTest.java @@ -0,0 +1,35 @@ +package domain; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import java.util.List; +import org.junit.jupiter.api.Test; + +public class PieceStorageTest { + + @Test + void 외부에서_주입받은_기물리스트로_생성된다() { + List piecesList = List.of( + Piece.of(TeamColor.CHO, PieceType.CANNON), + Piece.of(TeamColor.CHO, PieceType.ELEPHANT), + Piece.of(TeamColor.CHO, PieceType.GUARD)); + + PieceStorage pieceStorage = new PieceStorage(piecesList); + + assertThat(pieceStorage.getActivePieces()).isEqualTo(piecesList); + } + + @Test + void 활성_기물_조회_결과는_외부에서_수정할_수_없다() { + List piecesList = List.of( + Piece.of(TeamColor.CHO, PieceType.CANNON), + Piece.of(TeamColor.CHO, PieceType.ELEPHANT) + ); + + PieceStorage pieceStorage = new PieceStorage(piecesList); + + assertThatThrownBy(() -> + pieceStorage.getActivePieces().add(Piece.of(TeamColor.CHO, PieceType.GUARD)) + ).isInstanceOf(UnsupportedOperationException.class); + } +} From 42ebe3bfb5bfd6ff8204ddd95057cb92604bec5b Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Thu, 26 Mar 2026 20:50:54 +0900 Subject: [PATCH 20/82] =?UTF-8?q?refactor:=20=EA=B5=AC=EC=A1=B0=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=EC=9C=BC=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20Pie?= =?UTF-8?q?ceStorage=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/domain/PieceStorageTest.java | 35 ---------------------- 1 file changed, 35 deletions(-) delete mode 100644 src/test/java/domain/PieceStorageTest.java diff --git a/src/test/java/domain/PieceStorageTest.java b/src/test/java/domain/PieceStorageTest.java deleted file mode 100644 index 046abf04bf..0000000000 --- a/src/test/java/domain/PieceStorageTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package domain; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; -import java.util.List; -import org.junit.jupiter.api.Test; - -public class PieceStorageTest { - - @Test - void 외부에서_주입받은_기물리스트로_생성된다() { - List piecesList = List.of( - Piece.of(TeamColor.CHO, PieceType.CANNON), - Piece.of(TeamColor.CHO, PieceType.ELEPHANT), - Piece.of(TeamColor.CHO, PieceType.GUARD)); - - PieceStorage pieceStorage = new PieceStorage(piecesList); - - assertThat(pieceStorage.getActivePieces()).isEqualTo(piecesList); - } - - @Test - void 활성_기물_조회_결과는_외부에서_수정할_수_없다() { - List piecesList = List.of( - Piece.of(TeamColor.CHO, PieceType.CANNON), - Piece.of(TeamColor.CHO, PieceType.ELEPHANT) - ); - - PieceStorage pieceStorage = new PieceStorage(piecesList); - - assertThatThrownBy(() -> - pieceStorage.getActivePieces().add(Piece.of(TeamColor.CHO, PieceType.GUARD)) - ).isInstanceOf(UnsupportedOperationException.class); - } -} From 01759d809d0b5234772bf6bf8fa41eea5fe1f052 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Thu, 26 Mar 2026 21:20:50 +0900 Subject: [PATCH 21/82] test: add TurnManager test code --- src/test/java/domain/TurnManagerTest.java | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/test/java/domain/TurnManagerTest.java diff --git a/src/test/java/domain/TurnManagerTest.java b/src/test/java/domain/TurnManagerTest.java new file mode 100644 index 0000000000..f735db3a5f --- /dev/null +++ b/src/test/java/domain/TurnManagerTest.java @@ -0,0 +1,26 @@ +package domain; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + +public class TurnManagerTest { + + @BeforeEach + public void setUp(){ + TurnManager turnManager = new TurnManager(); + } + + @Test + public void 현재_턴이_누구인지_반환한다() { + assertThat(turnManager.getCurrentTurn()).isEqualTo(TeamColor.CHO); + + } + + @Test + public void 턴이_바뀌면_반대팀이_현재_턴이_된다() { + turnManager.progressTurn(); + assertThat(turnManager.getCurrentTurn()).isEqualTo(TeamColor.HAN); + + } +} From 93922c6d56c937d9c31dd4ad4096f77fe1d84c68 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Thu, 26 Mar 2026 21:27:20 +0900 Subject: [PATCH 22/82] feat: implement TurnManager --- src/main/java/domain/TurnManager.java | 25 +++++++++++++++++++++++ src/test/java/domain/TurnManagerTest.java | 4 +++- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/main/java/domain/TurnManager.java diff --git a/src/main/java/domain/TurnManager.java b/src/main/java/domain/TurnManager.java new file mode 100644 index 0000000000..71474ff904 --- /dev/null +++ b/src/main/java/domain/TurnManager.java @@ -0,0 +1,25 @@ +package domain; + +public class TurnManager { + + TeamColor teamColor; + int moveCount; + + public TurnManager(){ + teamColor = TeamColor.CHO; + moveCount = 0; + } + + public void progressTurn(){ + moveCount += 1; + if(teamColor.equals(TeamColor.CHO)) { + teamColor = TeamColor.HAN; + return; + } + teamColor = TeamColor.CHO; + } + + public TeamColor getCurrentTurn() { + return teamColor; + } +} diff --git a/src/test/java/domain/TurnManagerTest.java b/src/test/java/domain/TurnManagerTest.java index f735db3a5f..f4627bfc61 100644 --- a/src/test/java/domain/TurnManagerTest.java +++ b/src/test/java/domain/TurnManagerTest.java @@ -6,9 +6,11 @@ public class TurnManagerTest { + TurnManager turnManager; + @BeforeEach public void setUp(){ - TurnManager turnManager = new TurnManager(); + turnManager = new TurnManager(); } @Test From 7d3355bc774f9bb65ca33f34edcc19ef149ab97d Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 14:24:31 +0900 Subject: [PATCH 23/82] feat: implement InitalGameState --- src/main/java/domain/InitialGameState.java | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/main/java/domain/InitialGameState.java diff --git a/src/main/java/domain/InitialGameState.java b/src/main/java/domain/InitialGameState.java new file mode 100644 index 0000000000..7451ebe623 --- /dev/null +++ b/src/main/java/domain/InitialGameState.java @@ -0,0 +1,10 @@ +package domain; + +import java.util.List; +import java.util.Map; + +public record InitialGameState( + Map boardState, + List choPieces, + List hanPieces +) {} From 1330f25c17719d114143c5d9f3e657ebfb8274e9 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 14:26:31 +0900 Subject: [PATCH 24/82] test: create pawnMoveStrategy test code --- .../java/strategy/move/MoveStategyTest.java | 4 ++ .../strategy/move/PawnMoveStrategyTest.java | 42 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 src/test/java/strategy/move/MoveStategyTest.java create mode 100644 src/test/java/strategy/move/PawnMoveStrategyTest.java diff --git a/src/test/java/strategy/move/MoveStategyTest.java b/src/test/java/strategy/move/MoveStategyTest.java new file mode 100644 index 0000000000..12567d898b --- /dev/null +++ b/src/test/java/strategy/move/MoveStategyTest.java @@ -0,0 +1,4 @@ +package strategy.move; + +public class MoveStategyTest { +} diff --git a/src/test/java/strategy/move/PawnMoveStrategyTest.java b/src/test/java/strategy/move/PawnMoveStrategyTest.java new file mode 100644 index 0000000000..d8b91e15e2 --- /dev/null +++ b/src/test/java/strategy/move/PawnMoveStrategyTest.java @@ -0,0 +1,42 @@ +package strategy.move; + +import domain.Direction; +import domain.MovePath; +import domain.Piece; +import domain.PieceType; +import domain.TeamColor; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + +public class PawnMoveStrategyTest { + + public Piece piece; + + @BeforeEach + public void setUp() { + piece = Piece.of(TeamColor.CHO, PieceType.PAWN); + } + + + @Test + public void 초나라_졸은_북동서로_이동_가능하다() { + MoveStrategy moveStrategy = new PawnMoveStrategy(); + List movePathList = moveStrategy.getPaths(TeamColor.CHO); + assertThat(movePathList).contains(new MovePath(List.of(Direction.NORTH))); + assertThat(movePathList).contains(new MovePath(List.of(Direction.WEST))); + assertThat(movePathList).contains(new MovePath(List.of(Direction.EAST))); + assertThat(movePathList).doesNotContain(new MovePath(List.of(Direction.SOUTH))); + } + + @Test + public void 한나라_졸은_남동서로_이동_가능하다() { + MoveStrategy moveStrategy = new PawnMoveStrategy(); + List movePathList = moveStrategy.getPaths(TeamColor.HAN); + assertThat(movePathList).contains(new MovePath(List.of(Direction.SOUTH))); + assertThat(movePathList).contains(new MovePath(List.of(Direction.WEST))); + assertThat(movePathList).contains(new MovePath(List.of(Direction.EAST))); + assertThat(movePathList).doesNotContain(new MovePath(List.of(Direction.NORTH))); + } +} From af7cfaaf8730dc02a2e154b3374615b67c62f6ed Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 14:27:21 +0900 Subject: [PATCH 25/82] feat : implement PawnMoveStrategy --- src/main/java/domain/Direction.java | 28 +++++++++++++ src/main/java/domain/MovePath.java | 6 +++ src/main/java/strategy/move/MoveStrategy.java | 11 ++++++ .../java/strategy/move/PawnMoveStrategy.java | 39 +++++++++++++++++++ 4 files changed, 84 insertions(+) create mode 100644 src/main/java/domain/Direction.java create mode 100644 src/main/java/domain/MovePath.java create mode 100644 src/main/java/strategy/move/MoveStrategy.java create mode 100644 src/main/java/strategy/move/PawnMoveStrategy.java diff --git a/src/main/java/domain/Direction.java b/src/main/java/domain/Direction.java new file mode 100644 index 0000000000..8441ea6431 --- /dev/null +++ b/src/main/java/domain/Direction.java @@ -0,0 +1,28 @@ +package domain; + +public enum Direction { + NORTH(-1, 0), + SOUTH(1, 0), + EAST(0, 1), + WEST(0, -1), + NORTH_EAST(-1, 1), + NORTH_WEST(-1, -1), + SOUTH_EAST(1, 1), + SOUTH_WEST(1, -1); + + private final int dx; + private final int dy; + + Direction(int dx, int dy) { + this.dx = dx; + this.dy = dy; + } + + public int dx() { + return dx; + } + + public int dy() { + return dy; + } +} diff --git a/src/main/java/domain/MovePath.java b/src/main/java/domain/MovePath.java new file mode 100644 index 0000000000..0a36f8c55d --- /dev/null +++ b/src/main/java/domain/MovePath.java @@ -0,0 +1,6 @@ +package domain; + +import java.util.List; + +public record MovePath(List steps) {} + diff --git a/src/main/java/strategy/move/MoveStrategy.java b/src/main/java/strategy/move/MoveStrategy.java new file mode 100644 index 0000000000..0d52794a3b --- /dev/null +++ b/src/main/java/strategy/move/MoveStrategy.java @@ -0,0 +1,11 @@ +package strategy.move; + +import domain.MovePath; +import domain.TeamColor; +import java.util.List; + +public interface MoveStrategy { + + public List getPaths(TeamColor teamColor); + +} diff --git a/src/main/java/strategy/move/PawnMoveStrategy.java b/src/main/java/strategy/move/PawnMoveStrategy.java new file mode 100644 index 0000000000..3c5f30baed --- /dev/null +++ b/src/main/java/strategy/move/PawnMoveStrategy.java @@ -0,0 +1,39 @@ +package strategy.move; + +import domain.Direction; +import domain.MovePath; +import domain.TeamColor; +import java.util.List; + +public class PawnMoveStrategy implements MoveStrategy{ + + private static final List PATHS = List.of( + // 북쪽 베이스 + new MovePath(List.of(Direction.NORTH)), + // 남쪽 베이스 + new MovePath(List.of(Direction.SOUTH)), + // 동쪽 베이스 + new MovePath(List.of(Direction.EAST)), + // 서쪽 베이스 + new MovePath(List.of(Direction.WEST)) + ); + + @Override + public List getPaths(TeamColor teamColor) { + if (teamColor == TeamColor.CHO) { + return List.of( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)) + ); + } + + return List.of( + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)) + ); + } + + +} From 9bd2ff7247f9dbb03b764289c789b2d03001bbc9 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 14:31:45 +0900 Subject: [PATCH 26/82] test : create RookMoveStrategy test code --- .../strategy/move/RookMoveStrategyTest.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/test/java/strategy/move/RookMoveStrategyTest.java diff --git a/src/test/java/strategy/move/RookMoveStrategyTest.java b/src/test/java/strategy/move/RookMoveStrategyTest.java new file mode 100644 index 0000000000..e0a91e97df --- /dev/null +++ b/src/test/java/strategy/move/RookMoveStrategyTest.java @@ -0,0 +1,39 @@ +package strategy.move; + +import domain.Direction; +import domain.MovePath; +import domain.TeamColor; +import java.util.List; +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + +public class RookMoveStrategyTest { + + @Test + public void 차는_초나라에서_동서남북_4방향을_가진다() { + MoveStrategy strategy = new RookMoveStrategy(); + List paths = strategy.getPaths(TeamColor.CHO); + + assertThat(paths).hasSize(4); + assertThat(paths).containsExactlyInAnyOrder( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)) + ); + } + + @Test + public void 차는_한나라에서_동서남북_4방향을_가진다() { + MoveStrategy strategy = new RookMoveStrategy(); + List paths = strategy.getPaths(TeamColor.HAN); + + assertThat(paths).hasSize(4); + assertThat(paths).containsExactlyInAnyOrder( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)) + ); + } +} From 9bd2bea515ecaae9c327191bcb00f4b767c6a117 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 14:32:16 +0900 Subject: [PATCH 27/82] feat : implements RookMoveStrategy --- .../java/strategy/move/RookMoveStrategy.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/main/java/strategy/move/RookMoveStrategy.java diff --git a/src/main/java/strategy/move/RookMoveStrategy.java b/src/main/java/strategy/move/RookMoveStrategy.java new file mode 100644 index 0000000000..95336444b6 --- /dev/null +++ b/src/main/java/strategy/move/RookMoveStrategy.java @@ -0,0 +1,21 @@ +package strategy.move; + +import domain.Direction; +import domain.MovePath; +import domain.TeamColor; +import java.util.List; + +public class RookMoveStrategy implements MoveStrategy { + + private static final List PATHS = List.of( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)) + ); + + @Override + public List getPaths(TeamColor teamColor) { + return PATHS; + } +} From f9d52348595f2984029e6ee8ee37c71a2fad4704 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 14:35:41 +0900 Subject: [PATCH 28/82] test : implements KingMoveStrategy test code --- .../strategy/move/KingMoveStrategyTest.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/test/java/strategy/move/KingMoveStrategyTest.java diff --git a/src/test/java/strategy/move/KingMoveStrategyTest.java b/src/test/java/strategy/move/KingMoveStrategyTest.java new file mode 100644 index 0000000000..6260dbc612 --- /dev/null +++ b/src/test/java/strategy/move/KingMoveStrategyTest.java @@ -0,0 +1,48 @@ +package strategy.move; + +import domain.Direction; +import domain.MovePath; +import domain.TeamColor; +import java.util.List; +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + +public class KingMoveStrategyTest { + + @Test + public void 초나라_왕은_8방향으로_이동_가능하다() { + MoveStrategy strategy = new KingMoveStrategy(); + List paths = strategy.getPaths(TeamColor.CHO); + + assertThat(paths).hasSize(8); + assertThat(paths).containsExactlyInAnyOrder( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)), + new MovePath(List.of(Direction.NORTH_EAST)), + new MovePath(List.of(Direction.NORTH_WEST)), + new MovePath(List.of(Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.SOUTH_WEST)) + ); + } + + @Test + public void 한나라_왕은_8방향으로_이동_가능하다() { + MoveStrategy strategy = new KingMoveStrategy(); + List paths = strategy.getPaths(TeamColor.HAN); + + assertThat(paths).hasSize(8); + assertThat(paths).containsExactlyInAnyOrder( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)), + new MovePath(List.of(Direction.NORTH_EAST)), + new MovePath(List.of(Direction.NORTH_WEST)), + new MovePath(List.of(Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.SOUTH_WEST)) + ); + } +} + From d3fbf6a6cf56b28c82f67bf527a832e2ce584b1e Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 14:36:04 +0900 Subject: [PATCH 29/82] feat : implements KingMoveStrategy --- .../java/strategy/move/KingMoveStrategy.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/main/java/strategy/move/KingMoveStrategy.java diff --git a/src/main/java/strategy/move/KingMoveStrategy.java b/src/main/java/strategy/move/KingMoveStrategy.java new file mode 100644 index 0000000000..d2a357914d --- /dev/null +++ b/src/main/java/strategy/move/KingMoveStrategy.java @@ -0,0 +1,25 @@ +package strategy.move; + +import domain.Direction; +import domain.MovePath; +import domain.TeamColor; +import java.util.List; + +public class KingMoveStrategy implements MoveStrategy { + + private static final List PATHS = List.of( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)), + new MovePath(List.of(Direction.NORTH_EAST)), + new MovePath(List.of(Direction.NORTH_WEST)), + new MovePath(List.of(Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.SOUTH_WEST)) + ); + + @Override + public List getPaths(TeamColor teamColor) { + return PATHS; + } +} From dd279bd36f6dd5b77945990bd53517ad44583052 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 14:39:44 +0900 Subject: [PATCH 30/82] test: create HorseMoveStrategy test code --- .../strategy/move/HorseMoveStrategyTest.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/test/java/strategy/move/HorseMoveStrategyTest.java diff --git a/src/test/java/strategy/move/HorseMoveStrategyTest.java b/src/test/java/strategy/move/HorseMoveStrategyTest.java new file mode 100644 index 0000000000..23550b7131 --- /dev/null +++ b/src/test/java/strategy/move/HorseMoveStrategyTest.java @@ -0,0 +1,47 @@ +package strategy.move; + +import domain.Direction; +import domain.MovePath; +import domain.TeamColor; +import java.util.List; +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + +public class HorseMoveStrategyTest { + + @Test + public void 초나라_마는_직진1칸_대각선1칸으로_이루어진_8개의_경로를_가진다() { + MoveStrategy strategy = new HorseMoveStrategy(); + List paths = strategy.getPaths(TeamColor.CHO); + + assertThat(paths).hasSize(8); + assertThat(paths).contains( + new MovePath(List.of(Direction.NORTH, Direction.NORTH_EAST)), + new MovePath(List.of(Direction.NORTH, Direction.NORTH_WEST)), + new MovePath(List.of(Direction.EAST, Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.EAST, Direction. NORTH_EAST)), + new MovePath(List.of(Direction.SOUTH, Direction.SOUTH_WEST)), + new MovePath(List.of(Direction.SOUTH, Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.WEST, Direction.NORTH_WEST)), + new MovePath(List.of(Direction.WEST, Direction.SOUTH_WEST)) + ); + } + + @Test + public void 한나라_마는_직진1칸_대각선1칸으로_이루어진_8개의_경로를_가진다() { + MoveStrategy strategy = new HorseMoveStrategy(); + List paths = strategy.getPaths(TeamColor.HAN); + + assertThat(paths).hasSize(8); + assertThat(paths).contains( + new MovePath(List.of(Direction.NORTH, Direction.NORTH_EAST)), + new MovePath(List.of(Direction.NORTH, Direction.NORTH_WEST)), + new MovePath(List.of(Direction.EAST, Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.EAST, Direction. NORTH_EAST)), + new MovePath(List.of(Direction.SOUTH, Direction.SOUTH_WEST)), + new MovePath(List.of(Direction.SOUTH, Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.WEST, Direction.NORTH_WEST)), + new MovePath(List.of(Direction.WEST, Direction.SOUTH_WEST)) + ); + } +} \ No newline at end of file From 990feb4c8475793cf72097105ca6d507948f3bcb Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 14:40:07 +0900 Subject: [PATCH 31/82] feat: implement HorseMoveStrategy --- .../java/strategy/move/HorseMoveStrategy.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/main/java/strategy/move/HorseMoveStrategy.java diff --git a/src/main/java/strategy/move/HorseMoveStrategy.java b/src/main/java/strategy/move/HorseMoveStrategy.java new file mode 100644 index 0000000000..8ad762150e --- /dev/null +++ b/src/main/java/strategy/move/HorseMoveStrategy.java @@ -0,0 +1,25 @@ +package strategy.move; + +import domain.Direction; +import domain.MovePath; +import domain.TeamColor; +import java.util.List; + +public class HorseMoveStrategy implements MoveStrategy { + + private static final List PATHS = List.of( + new MovePath(List.of(Direction.NORTH, Direction.NORTH_EAST)), + new MovePath(List.of(Direction.NORTH, Direction.NORTH_WEST)), + new MovePath(List.of(Direction.SOUTH, Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.SOUTH, Direction.SOUTH_WEST)), + new MovePath(List.of(Direction.EAST, Direction.NORTH_EAST)), + new MovePath(List.of(Direction.EAST, Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.WEST, Direction.NORTH_WEST)), + new MovePath(List.of(Direction.WEST, Direction.SOUTH_WEST)) + ); + + @Override + public List getPaths(TeamColor teamColor) { + return PATHS; + } +} \ No newline at end of file From 3fa2daa45f9fb9b99cb73d4a61426933aca07e70 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 14:42:30 +0900 Subject: [PATCH 32/82] test : create CannonMoveStrategy test code --- .../strategy/move/CannonMoveStrategyTest.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/test/java/strategy/move/CannonMoveStrategyTest.java diff --git a/src/test/java/strategy/move/CannonMoveStrategyTest.java b/src/test/java/strategy/move/CannonMoveStrategyTest.java new file mode 100644 index 0000000000..e106269d32 --- /dev/null +++ b/src/test/java/strategy/move/CannonMoveStrategyTest.java @@ -0,0 +1,39 @@ +package strategy.move; + +import domain.Direction; +import domain.MovePath; +import domain.TeamColor; +import java.util.List; +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + +public class CannonMoveStrategyTest { + + @Test + public void 포는_초나라에서_동서남북_4방향을_가진다() { + MoveStrategy strategy = new RookMoveStrategy(); + List paths = strategy.getPaths(TeamColor.CHO); + + assertThat(paths).hasSize(4); + assertThat(paths).containsExactlyInAnyOrder( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)) + ); + } + + @Test + public void 포는_한나라에서_동서남북_4방향을_가진다() { + MoveStrategy strategy = new RookMoveStrategy(); + List paths = strategy.getPaths(TeamColor.HAN); + + assertThat(paths).hasSize(4); + assertThat(paths).containsExactlyInAnyOrder( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)) + ); + } +} From e0e88417008baf0648ed9a7eb1d41488af4587a0 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 14:43:36 +0900 Subject: [PATCH 33/82] test: create ElephantMoveStrategy test code --- .../strategy/move/CannonMoveStrategy.java | 21 +++++++++++ .../move/ElephantMoveStrategyTest.java | 37 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 src/main/java/strategy/move/CannonMoveStrategy.java create mode 100644 src/test/java/strategy/move/ElephantMoveStrategyTest.java diff --git a/src/main/java/strategy/move/CannonMoveStrategy.java b/src/main/java/strategy/move/CannonMoveStrategy.java new file mode 100644 index 0000000000..349b614639 --- /dev/null +++ b/src/main/java/strategy/move/CannonMoveStrategy.java @@ -0,0 +1,21 @@ +package strategy.move; + +import domain.Direction; +import domain.MovePath; +import domain.TeamColor; +import java.util.List; + +public class CannonMoveStrategy implements MoveStrategy { + + private static final List PATHS = List.of( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)) + ); + + @Override + public List getPaths(TeamColor teamColor) { + return PATHS; + } +} diff --git a/src/test/java/strategy/move/ElephantMoveStrategyTest.java b/src/test/java/strategy/move/ElephantMoveStrategyTest.java new file mode 100644 index 0000000000..522da57fce --- /dev/null +++ b/src/test/java/strategy/move/ElephantMoveStrategyTest.java @@ -0,0 +1,37 @@ +package strategy.move; + +import domain.Direction; +import domain.MovePath; +import domain.TeamColor; +import java.util.List; +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + +public class ElephantMoveStrategyTest { + + @Test + public void 초나라_상은_직진1칸_대각선2칸으로_이루어진_8개의_경로를_가진다() { + MoveStrategy strategy = new ElephantMoveStrategy(); + List paths = strategy.getPaths(TeamColor.CHO); + + assertThat(paths).hasSize(8); + assertThat(paths).contains( + new MovePath(List.of(Direction.NORTH, Direction.NORTH_EAST, Direction.NORTH_EAST)), + new MovePath(List.of(Direction.NORTH, Direction.NORTH_WEST, Direction.NORTH_WEST)), + new MovePath(List.of(Direction.EAST, Direction.NORTH_EAST, Direction.NORTH_EAST)) + ); + } + + @Test + public void 한나라_상은_직진1칸_대각선2칸으로_이루어진_8개의_경로를_가진다() { + MoveStrategy strategy = new ElephantMoveStrategy(); + List paths = strategy.getPaths(TeamColor.HAN); + + assertThat(paths).hasSize(8); + assertThat(paths).contains( + new MovePath(List.of(Direction.NORTH, Direction.NORTH_EAST, Direction.NORTH_EAST)), + new MovePath(List.of(Direction.NORTH, Direction.NORTH_WEST, Direction.NORTH_WEST)), + new MovePath(List.of(Direction.EAST, Direction.NORTH_EAST, Direction.NORTH_EAST)) + ); + } +} \ No newline at end of file From ed0e96f33ac296197d32b25cb7e93d709932f1f5 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 14:43:46 +0900 Subject: [PATCH 34/82] feat: implement ElephantMoveStrategy --- .../strategy/move/ElephantMoveStrategy.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/main/java/strategy/move/ElephantMoveStrategy.java diff --git a/src/main/java/strategy/move/ElephantMoveStrategy.java b/src/main/java/strategy/move/ElephantMoveStrategy.java new file mode 100644 index 0000000000..47d91fa388 --- /dev/null +++ b/src/main/java/strategy/move/ElephantMoveStrategy.java @@ -0,0 +1,25 @@ +package strategy.move; + +import domain.Direction; +import domain.MovePath; +import domain.TeamColor; +import java.util.List; + +public class ElephantMoveStrategy implements MoveStrategy { + + private static final List PATHS = List.of( + new MovePath(List.of(Direction.NORTH, Direction.NORTH_EAST, Direction.NORTH_EAST)), + new MovePath(List.of(Direction.NORTH, Direction.NORTH_WEST, Direction.NORTH_WEST)), + new MovePath(List.of(Direction.SOUTH, Direction.SOUTH_EAST, Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.SOUTH, Direction.SOUTH_WEST, Direction.SOUTH_WEST)), + new MovePath(List.of(Direction.EAST, Direction.NORTH_EAST, Direction.NORTH_EAST)), + new MovePath(List.of(Direction.EAST, Direction.SOUTH_EAST, Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.WEST, Direction.NORTH_WEST, Direction.NORTH_WEST)), + new MovePath(List.of(Direction.WEST, Direction.SOUTH_WEST, Direction.SOUTH_WEST)) + ); + + @Override + public List getPaths(TeamColor teamColor) { + return PATHS; + } +} \ No newline at end of file From c01cfa7a643b97c85fe5dff76aa50b82b15d7b39 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 14:45:13 +0900 Subject: [PATCH 35/82] test : create GuardMoveStrategy test code --- .../strategy/move/GuardMoveStrategyTest.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/test/java/strategy/move/GuardMoveStrategyTest.java diff --git a/src/test/java/strategy/move/GuardMoveStrategyTest.java b/src/test/java/strategy/move/GuardMoveStrategyTest.java new file mode 100644 index 0000000000..40c08b6a2a --- /dev/null +++ b/src/test/java/strategy/move/GuardMoveStrategyTest.java @@ -0,0 +1,48 @@ +package strategy.move; + +import domain.Direction; +import domain.MovePath; +import domain.TeamColor; +import java.util.List; +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + +public class GuardMoveStrategyTest { + + @Test + public void 초나라_사는_8방향으로_이동_가능하다() { + MoveStrategy strategy = new KingMoveStrategy(); + List paths = strategy.getPaths(TeamColor.CHO); + + assertThat(paths).hasSize(8); + assertThat(paths).containsExactlyInAnyOrder( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)), + new MovePath(List.of(Direction.NORTH_EAST)), + new MovePath(List.of(Direction.NORTH_WEST)), + new MovePath(List.of(Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.SOUTH_WEST)) + ); + } + + @Test + public void 한나라_사는_8방향으로_이동_가능하다() { + MoveStrategy strategy = new KingMoveStrategy(); + List paths = strategy.getPaths(TeamColor.HAN); + + assertThat(paths).hasSize(8); + assertThat(paths).containsExactlyInAnyOrder( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)), + new MovePath(List.of(Direction.NORTH_EAST)), + new MovePath(List.of(Direction.NORTH_WEST)), + new MovePath(List.of(Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.SOUTH_WEST)) + ); + } +} + From d70ce714bf3769b5d515db93693205944466f3d9 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 14:45:23 +0900 Subject: [PATCH 36/82] feat: implement GuardMoveStrategy --- .../java/strategy/move/GuardMoveStrategy.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/main/java/strategy/move/GuardMoveStrategy.java diff --git a/src/main/java/strategy/move/GuardMoveStrategy.java b/src/main/java/strategy/move/GuardMoveStrategy.java new file mode 100644 index 0000000000..c619d7975a --- /dev/null +++ b/src/main/java/strategy/move/GuardMoveStrategy.java @@ -0,0 +1,25 @@ +package strategy.move; + +import domain.Direction; +import domain.MovePath; +import domain.TeamColor; +import java.util.List; + +public class GuardMoveStrategy implements MoveStrategy { + + private static final List PATHS = List.of( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)), + new MovePath(List.of(Direction.NORTH_EAST)), + new MovePath(List.of(Direction.NORTH_WEST)), + new MovePath(List.of(Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.SOUTH_WEST)) + ); + + @Override + public List getPaths(TeamColor teamColor) { + return PATHS; + } +} From ddc21c5524cfbc15f7933c2dca54cef6dfad823d Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 16:37:02 +0900 Subject: [PATCH 37/82] test: PawnStrategy makeRoutes feature test --- .../java/strategy/move/PawnMoveStrategyTest.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/test/java/strategy/move/PawnMoveStrategyTest.java b/src/test/java/strategy/move/PawnMoveStrategyTest.java index d8b91e15e2..5b6a92ca59 100644 --- a/src/test/java/strategy/move/PawnMoveStrategyTest.java +++ b/src/test/java/strategy/move/PawnMoveStrategyTest.java @@ -4,6 +4,8 @@ import domain.MovePath; import domain.Piece; import domain.PieceType; +import domain.Position; +import domain.Route; import domain.TeamColor; import java.util.List; import org.junit.jupiter.api.BeforeEach; @@ -39,4 +41,18 @@ public void setUp() { assertThat(movePathList).contains(new MovePath(List.of(Direction.EAST))); assertThat(movePathList).doesNotContain(new MovePath(List.of(Direction.NORTH))); } + + + @Test + public void 초나라_졸이_정상적으로_진행경로_좌표를_안다(){ + Position curPos = Position.of(2,3); + MoveStrategy moveStrategy = new PawnMoveStrategy(); + + List routes = moveStrategy.makeRoutes(curPos, TeamColor.CHO); + assertThat(routes).containsExactlyInAnyOrder( + new Route(curPos, Position.of(1, 3), List.of()), + new Route(curPos, Position.of(2, 4), List.of()), + new Route(curPos, Position.of(2, 2), List.of()) + ); + } } From 4b08f053c41e593c4e07fcf4475d91ba7c0118d9 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 16:38:21 +0900 Subject: [PATCH 38/82] feat: implements makeRoutes method --- src/main/java/domain/Position.java | 8 ++++++ .../strategy/move/CannonMoveStrategy.java | 4 +++ .../strategy/move/ElephantMoveStrategy.java | 3 ++ .../java/strategy/move/GuardMoveStrategy.java | 4 +++ .../java/strategy/move/HorseMoveStrategy.java | 4 +++ .../java/strategy/move/KingMoveStrategy.java | 4 +++ src/main/java/strategy/move/MoveStrategy.java | 28 ++++++++++++++++++- .../java/strategy/move/PawnMoveStrategy.java | 15 ++-------- .../java/strategy/move/RookMoveStrategy.java | 4 +++ 9 files changed, 61 insertions(+), 13 deletions(-) diff --git a/src/main/java/domain/Position.java b/src/main/java/domain/Position.java index 500cda9eab..8c69a1d78d 100644 --- a/src/main/java/domain/Position.java +++ b/src/main/java/domain/Position.java @@ -11,6 +11,12 @@ private Position(Row row, Column column) { this.column = column; } + public Position next(Direction direction) { + int nextRow = this.row.value() + direction.dRow(); + int nextCol = this.column.value() + direction.dColumn(); + + return Position.of(nextRow, nextCol); + } public static Position of(int row, int column) { return new Position(new Row(row), new Column(column)); } @@ -29,4 +35,6 @@ public int hashCode() { return Objects.hash(row, column); } + + } diff --git a/src/main/java/strategy/move/CannonMoveStrategy.java b/src/main/java/strategy/move/CannonMoveStrategy.java index 349b614639..c863409269 100644 --- a/src/main/java/strategy/move/CannonMoveStrategy.java +++ b/src/main/java/strategy/move/CannonMoveStrategy.java @@ -2,6 +2,8 @@ import domain.Direction; import domain.MovePath; +import domain.Position; +import domain.Route; import domain.TeamColor; import java.util.List; @@ -18,4 +20,6 @@ public class CannonMoveStrategy implements MoveStrategy { public List getPaths(TeamColor teamColor) { return PATHS; } + + } diff --git a/src/main/java/strategy/move/ElephantMoveStrategy.java b/src/main/java/strategy/move/ElephantMoveStrategy.java index 47d91fa388..36a66783e6 100644 --- a/src/main/java/strategy/move/ElephantMoveStrategy.java +++ b/src/main/java/strategy/move/ElephantMoveStrategy.java @@ -2,6 +2,8 @@ import domain.Direction; import domain.MovePath; +import domain.Position; +import domain.Route; import domain.TeamColor; import java.util.List; @@ -22,4 +24,5 @@ public class ElephantMoveStrategy implements MoveStrategy { public List getPaths(TeamColor teamColor) { return PATHS; } + } \ No newline at end of file diff --git a/src/main/java/strategy/move/GuardMoveStrategy.java b/src/main/java/strategy/move/GuardMoveStrategy.java index c619d7975a..044cd6e1bd 100644 --- a/src/main/java/strategy/move/GuardMoveStrategy.java +++ b/src/main/java/strategy/move/GuardMoveStrategy.java @@ -2,6 +2,8 @@ import domain.Direction; import domain.MovePath; +import domain.Position; +import domain.Route; import domain.TeamColor; import java.util.List; @@ -22,4 +24,6 @@ public class GuardMoveStrategy implements MoveStrategy { public List getPaths(TeamColor teamColor) { return PATHS; } + + } diff --git a/src/main/java/strategy/move/HorseMoveStrategy.java b/src/main/java/strategy/move/HorseMoveStrategy.java index 8ad762150e..8babbbb9a3 100644 --- a/src/main/java/strategy/move/HorseMoveStrategy.java +++ b/src/main/java/strategy/move/HorseMoveStrategy.java @@ -2,6 +2,8 @@ import domain.Direction; import domain.MovePath; +import domain.Position; +import domain.Route; import domain.TeamColor; import java.util.List; @@ -22,4 +24,6 @@ public class HorseMoveStrategy implements MoveStrategy { public List getPaths(TeamColor teamColor) { return PATHS; } + + } \ No newline at end of file diff --git a/src/main/java/strategy/move/KingMoveStrategy.java b/src/main/java/strategy/move/KingMoveStrategy.java index d2a357914d..31dddd2b1d 100644 --- a/src/main/java/strategy/move/KingMoveStrategy.java +++ b/src/main/java/strategy/move/KingMoveStrategy.java @@ -2,6 +2,8 @@ import domain.Direction; import domain.MovePath; +import domain.Position; +import domain.Route; import domain.TeamColor; import java.util.List; @@ -22,4 +24,6 @@ public class KingMoveStrategy implements MoveStrategy { public List getPaths(TeamColor teamColor) { return PATHS; } + + } diff --git a/src/main/java/strategy/move/MoveStrategy.java b/src/main/java/strategy/move/MoveStrategy.java index 0d52794a3b..b3e9db1f4f 100644 --- a/src/main/java/strategy/move/MoveStrategy.java +++ b/src/main/java/strategy/move/MoveStrategy.java @@ -1,11 +1,37 @@ package strategy.move; import domain.MovePath; +import domain.Position; import domain.TeamColor; import java.util.List; +import domain.Route; public interface MoveStrategy { - public List getPaths(TeamColor teamColor); + List getPaths(TeamColor teamColor); + + default List makeRoutes(Position curPos, TeamColor teamColor) { + List validRoutes = new ArrayList<>(); + List paths = getPaths(teamColor); + + for (MovePath path : paths) { + List steps = path.steps(); + Position currentPos = curPos; + List intermediates = new ArrayList<>(); + + + for (int i = 0; i < steps.size(); i++) { + currentPos = currentPos.next(steps.get(i)); + + if (i < steps.size() - 1) { + intermediates.add(currentPos); + } + } + validRoutes.add(new Route(curPos, currentPos, intermediates)); + } + + return validRoutes; + } + } diff --git a/src/main/java/strategy/move/PawnMoveStrategy.java b/src/main/java/strategy/move/PawnMoveStrategy.java index 3c5f30baed..cf89f8f65f 100644 --- a/src/main/java/strategy/move/PawnMoveStrategy.java +++ b/src/main/java/strategy/move/PawnMoveStrategy.java @@ -2,22 +2,14 @@ import domain.Direction; import domain.MovePath; +import domain.Position; +import domain.Route; import domain.TeamColor; +import java.util.ArrayList; import java.util.List; public class PawnMoveStrategy implements MoveStrategy{ - private static final List PATHS = List.of( - // 북쪽 베이스 - new MovePath(List.of(Direction.NORTH)), - // 남쪽 베이스 - new MovePath(List.of(Direction.SOUTH)), - // 동쪽 베이스 - new MovePath(List.of(Direction.EAST)), - // 서쪽 베이스 - new MovePath(List.of(Direction.WEST)) - ); - @Override public List getPaths(TeamColor teamColor) { if (teamColor == TeamColor.CHO) { @@ -35,5 +27,4 @@ public List getPaths(TeamColor teamColor) { ); } - } diff --git a/src/main/java/strategy/move/RookMoveStrategy.java b/src/main/java/strategy/move/RookMoveStrategy.java index 95336444b6..679ce56c76 100644 --- a/src/main/java/strategy/move/RookMoveStrategy.java +++ b/src/main/java/strategy/move/RookMoveStrategy.java @@ -2,6 +2,8 @@ import domain.Direction; import domain.MovePath; +import domain.Position; +import domain.Route; import domain.TeamColor; import java.util.List; @@ -18,4 +20,6 @@ public class RookMoveStrategy implements MoveStrategy { public List getPaths(TeamColor teamColor) { return PATHS; } + + } From 16470041e6b839aa16b449a64dd8e0d10d07bd92 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 16:38:32 +0900 Subject: [PATCH 39/82] feat: implement GuardMoveStrategy --- src/main/java/domain/Route.java | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/main/java/domain/Route.java diff --git a/src/main/java/domain/Route.java b/src/main/java/domain/Route.java new file mode 100644 index 0000000000..97bebe5ad4 --- /dev/null +++ b/src/main/java/domain/Route.java @@ -0,0 +1,5 @@ +package domain; + +import java.util.List; + +public record Route(Position startPos, Position endPos, List intermeidateNodes) {} From 2b0878c15935ea8d0a83be59f25fc409c1f7ff58 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 16:56:18 +0900 Subject: [PATCH 40/82] test: create PawnStrategyTest canJump Test --- .../strategy/move/PawnMoveStrategyTest.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/test/java/strategy/move/PawnMoveStrategyTest.java b/src/test/java/strategy/move/PawnMoveStrategyTest.java index 5b6a92ca59..ea72aac8df 100644 --- a/src/test/java/strategy/move/PawnMoveStrategyTest.java +++ b/src/test/java/strategy/move/PawnMoveStrategyTest.java @@ -55,4 +55,24 @@ public void setUp() { new Route(curPos, Position.of(2, 2), List.of()) ); } + + @Test + public void 졸은_장애물이_없으면_지나갈수_있다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); + + List blockingPieces = List.of(); + boolean canJumpTo = moveStrategy.canJump(blockingPieces); + + assertThat(canJumpTo).isTrue(); + } + + @Test + public void 졸은_장애물이_하나라도_있으면_지나갈수_없다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); + + List blockingPieces = List.of(Piece.of(TeamColor.CHO,PieceType.CANNON)); + boolean canJumpTo = moveStrategy.canJump(blockingPieces); + + assertThat(canJumpTo).isFalse(); + } } From 2e4a9cf166861aeffc15d74de9106a9489ab121a Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 16:58:16 +0900 Subject: [PATCH 41/82] feat: implement moveStrategys canJump --- src/main/java/strategy/move/CannonMoveStrategy.java | 7 ++++++- src/main/java/strategy/move/ElephantMoveStrategy.java | 9 +++++++++ src/main/java/strategy/move/HorseMoveStrategy.java | 7 ++++++- src/main/java/strategy/move/KingMoveStrategy.java | 9 ++++++++- src/main/java/strategy/move/MoveStrategy.java | 3 +++ src/main/java/strategy/move/PawnMoveStrategy.java | 10 ++++++++++ src/main/java/strategy/move/RookMoveStrategy.java | 9 +++++++++ 7 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/main/java/strategy/move/CannonMoveStrategy.java b/src/main/java/strategy/move/CannonMoveStrategy.java index c863409269..c94f8666c6 100644 --- a/src/main/java/strategy/move/CannonMoveStrategy.java +++ b/src/main/java/strategy/move/CannonMoveStrategy.java @@ -2,6 +2,7 @@ import domain.Direction; import domain.MovePath; +import domain.Piece; import domain.Position; import domain.Route; import domain.TeamColor; @@ -21,5 +22,9 @@ public List getPaths(TeamColor teamColor) { return PATHS; } - + @Override + public boolean canJump(List blockingPieces) { + if (blockingPieces.isEmpty()) return true; + return false; + } } diff --git a/src/main/java/strategy/move/ElephantMoveStrategy.java b/src/main/java/strategy/move/ElephantMoveStrategy.java index 36a66783e6..446fcbd7a6 100644 --- a/src/main/java/strategy/move/ElephantMoveStrategy.java +++ b/src/main/java/strategy/move/ElephantMoveStrategy.java @@ -2,6 +2,7 @@ import domain.Direction; import domain.MovePath; +import domain.Piece; import domain.Position; import domain.Route; import domain.TeamColor; @@ -25,4 +26,12 @@ public List getPaths(TeamColor teamColor) { return PATHS; } + @Override + public boolean canJump(List blockingPieces) { + if (blockingPieces.isEmpty()) { + return true; + } + return false; + } + } \ No newline at end of file diff --git a/src/main/java/strategy/move/HorseMoveStrategy.java b/src/main/java/strategy/move/HorseMoveStrategy.java index 8babbbb9a3..e3670a3d53 100644 --- a/src/main/java/strategy/move/HorseMoveStrategy.java +++ b/src/main/java/strategy/move/HorseMoveStrategy.java @@ -2,6 +2,7 @@ import domain.Direction; import domain.MovePath; +import domain.Piece; import domain.Position; import domain.Route; import domain.TeamColor; @@ -25,5 +26,9 @@ public List getPaths(TeamColor teamColor) { return PATHS; } - + @Override + public boolean canJump(List blockingPieces) { + if (blockingPieces.isEmpty()) return true; + return false; + } } \ No newline at end of file diff --git a/src/main/java/strategy/move/KingMoveStrategy.java b/src/main/java/strategy/move/KingMoveStrategy.java index 31dddd2b1d..ed07d8851f 100644 --- a/src/main/java/strategy/move/KingMoveStrategy.java +++ b/src/main/java/strategy/move/KingMoveStrategy.java @@ -2,6 +2,7 @@ import domain.Direction; import domain.MovePath; +import domain.Piece; import domain.Position; import domain.Route; import domain.TeamColor; @@ -25,5 +26,11 @@ public List getPaths(TeamColor teamColor) { return PATHS; } - + @Override + public boolean canJump(List blockingPieces) { + if (blockingPieces.isEmpty()) { + return true; + } + return false; + } } diff --git a/src/main/java/strategy/move/MoveStrategy.java b/src/main/java/strategy/move/MoveStrategy.java index b3e9db1f4f..86d2d6648f 100644 --- a/src/main/java/strategy/move/MoveStrategy.java +++ b/src/main/java/strategy/move/MoveStrategy.java @@ -5,6 +5,7 @@ import domain.TeamColor; import java.util.List; import domain.Route; +import domain.Piece; public interface MoveStrategy { @@ -33,5 +34,7 @@ default List makeRoutes(Position curPos, TeamColor teamColor) { return validRoutes; } + public boolean canJump(List blockingPieces); + } diff --git a/src/main/java/strategy/move/PawnMoveStrategy.java b/src/main/java/strategy/move/PawnMoveStrategy.java index cf89f8f65f..102a15c6f3 100644 --- a/src/main/java/strategy/move/PawnMoveStrategy.java +++ b/src/main/java/strategy/move/PawnMoveStrategy.java @@ -2,6 +2,7 @@ import domain.Direction; import domain.MovePath; +import domain.Piece; import domain.Position; import domain.Route; import domain.TeamColor; @@ -10,6 +11,7 @@ public class PawnMoveStrategy implements MoveStrategy{ + @Override public List getPaths(TeamColor teamColor) { if (teamColor == TeamColor.CHO) { @@ -27,4 +29,12 @@ public List getPaths(TeamColor teamColor) { ); } + @Override + public boolean canJump(List blockingPieces) { + if (blockingPieces.isEmpty()) { + return true; + } + return false; + } + } diff --git a/src/main/java/strategy/move/RookMoveStrategy.java b/src/main/java/strategy/move/RookMoveStrategy.java index 679ce56c76..8277d1e112 100644 --- a/src/main/java/strategy/move/RookMoveStrategy.java +++ b/src/main/java/strategy/move/RookMoveStrategy.java @@ -2,6 +2,7 @@ import domain.Direction; import domain.MovePath; +import domain.Piece; import domain.Position; import domain.Route; import domain.TeamColor; @@ -22,4 +23,12 @@ public List getPaths(TeamColor teamColor) { } + @Override + public boolean canJump(List blockingPieces) { + if (blockingPieces.isEmpty()) { + return true; + } + return false; + } + } From b0d93dd8006e4c0035e2b586001796262557d6ac Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 16:58:46 +0900 Subject: [PATCH 42/82] refactor : modify x,y -> row, column --- src/main/java/domain/Direction.java | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/domain/Direction.java b/src/main/java/domain/Direction.java index 8441ea6431..cf39c82c46 100644 --- a/src/main/java/domain/Direction.java +++ b/src/main/java/domain/Direction.java @@ -10,19 +10,19 @@ public enum Direction { SOUTH_EAST(1, 1), SOUTH_WEST(1, -1); - private final int dx; - private final int dy; + private final int dRow; + private final int dColumn; - Direction(int dx, int dy) { - this.dx = dx; - this.dy = dy; + Direction(int dRow, int dColumn) { + this.dRow = dRow; + this.dColumn = dColumn; } - public int dx() { - return dx; + public int dRow() { + return dRow; } - public int dy() { - return dy; + public int dColumn() { + return dColumn; } -} +} \ No newline at end of file From d3ba3d0aff5b7202a6a8740840264cd485b951e3 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 17:00:36 +0900 Subject: [PATCH 43/82] =?UTF-8?q?test:=20=ED=8F=AC=EB=A5=BC=20=EC=A0=9C?= =?UTF-8?q?=EC=99=B8=ED=95=9C=20=EA=B8=B0=EB=AC=BC=EB=93=A4=EC=9D=98=20?= =?UTF-8?q?=EC=9E=A5=EC=95=A0=EB=AC=BC=20=EC=A0=90=ED=94=84=20=EA=B0=80?= =?UTF-8?q?=EB=8A=A5=20=EC=97=AC=EB=B6=80=20=ED=85=8C=EC=8A=A4=ED=8A=B8=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 --- .../move/ElephantMoveStrategyTest.java | 22 +++++++++++++++++++ .../strategy/move/GuardMoveStrategyTest.java | 22 +++++++++++++++++++ .../strategy/move/HorseMoveStrategyTest.java | 22 +++++++++++++++++++ .../strategy/move/KingMoveStrategyTest.java | 22 +++++++++++++++++++ .../java/strategy/move/MoveStategyTest.java | 4 ++++ .../strategy/move/RookMoveStrategyTest.java | 22 +++++++++++++++++++ 6 files changed, 114 insertions(+) diff --git a/src/test/java/strategy/move/ElephantMoveStrategyTest.java b/src/test/java/strategy/move/ElephantMoveStrategyTest.java index 522da57fce..6477538dc4 100644 --- a/src/test/java/strategy/move/ElephantMoveStrategyTest.java +++ b/src/test/java/strategy/move/ElephantMoveStrategyTest.java @@ -2,6 +2,8 @@ import domain.Direction; import domain.MovePath; +import domain.Piece; +import domain.PieceType; import domain.TeamColor; import java.util.List; import org.junit.jupiter.api.Test; @@ -34,4 +36,24 @@ public class ElephantMoveStrategyTest { new MovePath(List.of(Direction.EAST, Direction.NORTH_EAST, Direction.NORTH_EAST)) ); } + + @Test + public void 상은_장애물이_없으면_지나갈수_있다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); + + List blockingPieces = List.of(); + boolean canJumpTo = moveStrategy.canJump(blockingPieces); + + assertThat(canJumpTo).isTrue(); + } + + @Test + public void 상은_장애물이_하나라도_있으면_지나갈수_없다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); + + List blockingPieces = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); + boolean canJumpTo = moveStrategy.canJump(blockingPieces); + + assertThat(canJumpTo).isFalse(); + } } \ No newline at end of file diff --git a/src/test/java/strategy/move/GuardMoveStrategyTest.java b/src/test/java/strategy/move/GuardMoveStrategyTest.java index 40c08b6a2a..c8916a739d 100644 --- a/src/test/java/strategy/move/GuardMoveStrategyTest.java +++ b/src/test/java/strategy/move/GuardMoveStrategyTest.java @@ -2,6 +2,8 @@ import domain.Direction; import domain.MovePath; +import domain.Piece; +import domain.PieceType; import domain.TeamColor; import java.util.List; import org.junit.jupiter.api.Test; @@ -44,5 +46,25 @@ public class GuardMoveStrategyTest { new MovePath(List.of(Direction.SOUTH_WEST)) ); } + + @Test + public void 사는_장애물이_없으면_지나갈수_있다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); + + List blockingPieces = List.of(); + boolean canJumpTo = moveStrategy.canJump(blockingPieces); + + assertThat(canJumpTo).isTrue(); + } + + @Test + public void 사는_장애물이_하나라도_있으면_지나갈수_없다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); + + List blockingPieces = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); + boolean canJumpTo = moveStrategy.canJump(blockingPieces); + + assertThat(canJumpTo).isFalse(); + } } diff --git a/src/test/java/strategy/move/HorseMoveStrategyTest.java b/src/test/java/strategy/move/HorseMoveStrategyTest.java index 23550b7131..82fa198ae0 100644 --- a/src/test/java/strategy/move/HorseMoveStrategyTest.java +++ b/src/test/java/strategy/move/HorseMoveStrategyTest.java @@ -2,6 +2,8 @@ import domain.Direction; import domain.MovePath; +import domain.Piece; +import domain.PieceType; import domain.TeamColor; import java.util.List; import org.junit.jupiter.api.Test; @@ -44,4 +46,24 @@ public class HorseMoveStrategyTest { new MovePath(List.of(Direction.WEST, Direction.SOUTH_WEST)) ); } + + @Test + public void 마는_장애물이_없으면_지나갈수_있다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); + + List blockingPieces = List.of(); + boolean canJumpTo = moveStrategy.canJump(blockingPieces); + + assertThat(canJumpTo).isTrue(); + } + + @Test + public void 마는_장애물이_하나라도_있으면_지나갈수_없다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); + + List blockingPieces = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); + boolean canJumpTo = moveStrategy.canJump(blockingPieces); + + assertThat(canJumpTo).isFalse(); + } } \ No newline at end of file diff --git a/src/test/java/strategy/move/KingMoveStrategyTest.java b/src/test/java/strategy/move/KingMoveStrategyTest.java index 6260dbc612..9c4861dfd6 100644 --- a/src/test/java/strategy/move/KingMoveStrategyTest.java +++ b/src/test/java/strategy/move/KingMoveStrategyTest.java @@ -2,6 +2,8 @@ import domain.Direction; import domain.MovePath; +import domain.Piece; +import domain.PieceType; import domain.TeamColor; import java.util.List; import org.junit.jupiter.api.Test; @@ -44,5 +46,25 @@ public class KingMoveStrategyTest { new MovePath(List.of(Direction.SOUTH_WEST)) ); } + + @Test + public void 왕은_장애물이_없으면_지나갈수_있다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); + + List blockingPieces = List.of(); + boolean canJumpTo = moveStrategy.canJump(blockingPieces); + + assertThat(canJumpTo).isTrue(); + } + + @Test + public void 왕은_장애물이_하나라도_있으면_지나갈수_없다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); + + List blockingPieces = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); + boolean canJumpTo = moveStrategy.canJump(blockingPieces); + + assertThat(canJumpTo).isFalse(); + } } diff --git a/src/test/java/strategy/move/MoveStategyTest.java b/src/test/java/strategy/move/MoveStategyTest.java index 12567d898b..9bbc2d251e 100644 --- a/src/test/java/strategy/move/MoveStategyTest.java +++ b/src/test/java/strategy/move/MoveStategyTest.java @@ -1,4 +1,8 @@ package strategy.move; +import org.junit.jupiter.api.Test; + public class MoveStategyTest { + + } diff --git a/src/test/java/strategy/move/RookMoveStrategyTest.java b/src/test/java/strategy/move/RookMoveStrategyTest.java index e0a91e97df..521e7abe79 100644 --- a/src/test/java/strategy/move/RookMoveStrategyTest.java +++ b/src/test/java/strategy/move/RookMoveStrategyTest.java @@ -2,6 +2,8 @@ import domain.Direction; import domain.MovePath; +import domain.Piece; +import domain.PieceType; import domain.TeamColor; import java.util.List; import org.junit.jupiter.api.Test; @@ -36,4 +38,24 @@ public class RookMoveStrategyTest { new MovePath(List.of(Direction.WEST)) ); } + + @Test + public void 차는_장애물이_없으면_지나갈수_있다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); + + List blockingPieces = List.of(); + boolean canJumpTo = moveStrategy.canJump(blockingPieces); + + assertThat(canJumpTo).isTrue(); + } + + @Test + public void 차는_장애물이_하나라도_있으면_지나갈수_없다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); + + List blockingPieces = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); + boolean canJumpTo = moveStrategy.canJump(blockingPieces); + + assertThat(canJumpTo).isFalse(); + } } From 6a8f23823153a8165582d4f7a1c5c7d458dc029a Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 18:21:42 +0900 Subject: [PATCH 44/82] =?UTF-8?q?feat:=20BlockingPieces=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=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/BlockingPieces.java | 43 +++++++++++++++++++ .../strategy/move/CannonMoveStrategy.java | 20 +++++++-- .../strategy/move/ElephantMoveStrategy.java | 7 +-- .../java/strategy/move/GuardMoveStrategy.java | 9 ++++ .../java/strategy/move/HorseMoveStrategy.java | 10 +++-- .../java/strategy/move/KingMoveStrategy.java | 5 ++- src/main/java/strategy/move/MoveStrategy.java | 5 ++- .../java/strategy/move/PawnMoveStrategy.java | 5 ++- .../java/strategy/move/RookMoveStrategy.java | 8 ++-- .../strategy/move/CannonMoveStrategyTest.java | 25 +++++++++++ .../move/ElephantMoveStrategyTest.java | 12 +++--- .../strategy/move/GuardMoveStrategyTest.java | 11 +++-- .../strategy/move/HorseMoveStrategyTest.java | 11 +++-- .../strategy/move/KingMoveStrategyTest.java | 11 +++-- .../strategy/move/PawnMoveStrategyTest.java | 11 +++-- .../strategy/move/RookMoveStrategyTest.java | 11 +++-- 16 files changed, 159 insertions(+), 45 deletions(-) create mode 100644 src/main/java/domain/BlockingPieces.java diff --git a/src/main/java/domain/BlockingPieces.java b/src/main/java/domain/BlockingPieces.java new file mode 100644 index 0000000000..4351545cc0 --- /dev/null +++ b/src/main/java/domain/BlockingPieces.java @@ -0,0 +1,43 @@ +package domain; + +import java.util.List; + +public class BlockingPieces { + + private int MAX_PIECES_ON_ROUTE = 2; + private final List pieces; + + public BlockingPieces(List pieces) { + if (pieces.size() > MAX_PIECES_ON_ROUTE) { + throw new IllegalArgumentException("경로 상의 기물은 최대 "+ MAX_PIECES_ON_ROUTE+ "개만 존재할 수 있습니다."); + } + this.pieces = List.copyOf(pieces); + } + + public boolean isFirstPieceCannon() { + if (pieces.isEmpty()) { + return false; + } + return pieces.getFirst().getPieceType() == PieceType.CANNON; // Java 21+ 문법 + } + + + public boolean isLastPieceCannon() { + if (pieces.size() < MAX_PIECES_ON_ROUTE) { + return false; + } + return pieces.getLast().getPieceType() == PieceType.CANNON; + } + + public boolean isLastPieceSameTeam(TeamColor myTeam) { + if (pieces.size() < MAX_PIECES_ON_ROUTE) { + return false; + } + return pieces.getLast().getTeamColor() == myTeam; + } + + public int size() { + return pieces.size(); + } + +} \ No newline at end of file diff --git a/src/main/java/strategy/move/CannonMoveStrategy.java b/src/main/java/strategy/move/CannonMoveStrategy.java index c94f8666c6..76edcbfe70 100644 --- a/src/main/java/strategy/move/CannonMoveStrategy.java +++ b/src/main/java/strategy/move/CannonMoveStrategy.java @@ -1,5 +1,6 @@ package strategy.move; +import domain.BlockingPieces; import domain.Direction; import domain.MovePath; import domain.Piece; @@ -23,8 +24,21 @@ public List getPaths(TeamColor teamColor) { } @Override - public boolean canJump(List blockingPieces) { - if (blockingPieces.isEmpty()) return true; - return false; + public boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam) { + if (blockingPieces.size() == 0) { + return false; + } + + if (blockingPieces.isFirstPieceCannon()) { + return false; + } + + if (blockingPieces.size() == 2) { + if (blockingPieces.isLastPieceCannon() || blockingPieces.isLastPieceSameTeam(myTeam)) { + return false; + } + } + + return true; } } diff --git a/src/main/java/strategy/move/ElephantMoveStrategy.java b/src/main/java/strategy/move/ElephantMoveStrategy.java index 446fcbd7a6..d22178054c 100644 --- a/src/main/java/strategy/move/ElephantMoveStrategy.java +++ b/src/main/java/strategy/move/ElephantMoveStrategy.java @@ -1,5 +1,6 @@ package strategy.move; +import domain.BlockingPieces; import domain.Direction; import domain.MovePath; import domain.Piece; @@ -8,7 +9,7 @@ import domain.TeamColor; import java.util.List; -public class ElephantMoveStrategy implements MoveStrategy { + public class ElephantMoveStrategy implements MoveStrategy { private static final List PATHS = List.of( new MovePath(List.of(Direction.NORTH, Direction.NORTH_EAST, Direction.NORTH_EAST)), @@ -27,8 +28,8 @@ public List getPaths(TeamColor teamColor) { } @Override - public boolean canJump(List blockingPieces) { - if (blockingPieces.isEmpty()) { + public boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam) { + if (blockingPieces.size() == 0) { return true; } return false; diff --git a/src/main/java/strategy/move/GuardMoveStrategy.java b/src/main/java/strategy/move/GuardMoveStrategy.java index 044cd6e1bd..f266344461 100644 --- a/src/main/java/strategy/move/GuardMoveStrategy.java +++ b/src/main/java/strategy/move/GuardMoveStrategy.java @@ -1,7 +1,9 @@ package strategy.move; +import domain.BlockingPieces; import domain.Direction; import domain.MovePath; +import domain.Piece; import domain.Position; import domain.Route; import domain.TeamColor; @@ -25,5 +27,12 @@ public List getPaths(TeamColor teamColor) { return PATHS; } + @Override + public boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam) { + if (blockingPieces.size() == 0) { + return true; + } + return false; + } } diff --git a/src/main/java/strategy/move/HorseMoveStrategy.java b/src/main/java/strategy/move/HorseMoveStrategy.java index e3670a3d53..c87cc53cc1 100644 --- a/src/main/java/strategy/move/HorseMoveStrategy.java +++ b/src/main/java/strategy/move/HorseMoveStrategy.java @@ -1,10 +1,10 @@ package strategy.move; +import domain.BlockingPieces; import domain.Direction; import domain.MovePath; import domain.Piece; -import domain.Position; -import domain.Route; + import domain.TeamColor; import java.util.List; @@ -27,8 +27,10 @@ public List getPaths(TeamColor teamColor) { } @Override - public boolean canJump(List blockingPieces) { - if (blockingPieces.isEmpty()) return true; + public boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam) { + if (blockingPieces.size() == 0) { + return true; + } return false; } } \ No newline at end of file diff --git a/src/main/java/strategy/move/KingMoveStrategy.java b/src/main/java/strategy/move/KingMoveStrategy.java index ed07d8851f..b572c02065 100644 --- a/src/main/java/strategy/move/KingMoveStrategy.java +++ b/src/main/java/strategy/move/KingMoveStrategy.java @@ -1,5 +1,6 @@ package strategy.move; +import domain.BlockingPieces; import domain.Direction; import domain.MovePath; import domain.Piece; @@ -27,8 +28,8 @@ public List getPaths(TeamColor teamColor) { } @Override - public boolean canJump(List blockingPieces) { - if (blockingPieces.isEmpty()) { + public boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam) { + if (blockingPieces.size()==0) { return true; } return false; diff --git a/src/main/java/strategy/move/MoveStrategy.java b/src/main/java/strategy/move/MoveStrategy.java index 86d2d6648f..33d6d7dd1d 100644 --- a/src/main/java/strategy/move/MoveStrategy.java +++ b/src/main/java/strategy/move/MoveStrategy.java @@ -1,8 +1,11 @@ package strategy.move; +import domain.BlockingPieces; +import domain.Direction; import domain.MovePath; import domain.Position; import domain.TeamColor; +import java.util.ArrayList; import java.util.List; import domain.Route; import domain.Piece; @@ -34,7 +37,7 @@ default List makeRoutes(Position curPos, TeamColor teamColor) { return validRoutes; } - public boolean canJump(List blockingPieces); + boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam); } diff --git a/src/main/java/strategy/move/PawnMoveStrategy.java b/src/main/java/strategy/move/PawnMoveStrategy.java index 102a15c6f3..65c190ba30 100644 --- a/src/main/java/strategy/move/PawnMoveStrategy.java +++ b/src/main/java/strategy/move/PawnMoveStrategy.java @@ -1,5 +1,6 @@ package strategy.move; +import domain.BlockingPieces; import domain.Direction; import domain.MovePath; import domain.Piece; @@ -30,8 +31,8 @@ public List getPaths(TeamColor teamColor) { } @Override - public boolean canJump(List blockingPieces) { - if (blockingPieces.isEmpty()) { + public boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam) { + if (blockingPieces.size()==0) { return true; } return false; diff --git a/src/main/java/strategy/move/RookMoveStrategy.java b/src/main/java/strategy/move/RookMoveStrategy.java index 8277d1e112..67fed4c48d 100644 --- a/src/main/java/strategy/move/RookMoveStrategy.java +++ b/src/main/java/strategy/move/RookMoveStrategy.java @@ -1,10 +1,8 @@ package strategy.move; +import domain.BlockingPieces; import domain.Direction; import domain.MovePath; -import domain.Piece; -import domain.Position; -import domain.Route; import domain.TeamColor; import java.util.List; @@ -24,8 +22,8 @@ public List getPaths(TeamColor teamColor) { @Override - public boolean canJump(List blockingPieces) { - if (blockingPieces.isEmpty()) { + public boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam) { + if (blockingPieces.size() == 0) { return true; } return false; diff --git a/src/test/java/strategy/move/CannonMoveStrategyTest.java b/src/test/java/strategy/move/CannonMoveStrategyTest.java index e106269d32..18722b5612 100644 --- a/src/test/java/strategy/move/CannonMoveStrategyTest.java +++ b/src/test/java/strategy/move/CannonMoveStrategyTest.java @@ -1,7 +1,10 @@ package strategy.move; +import domain.BlockingPieces; import domain.Direction; import domain.MovePath; +import domain.Piece; +import domain.PieceType; import domain.TeamColor; import java.util.List; import org.junit.jupiter.api.Test; @@ -36,4 +39,26 @@ public class CannonMoveStrategyTest { new MovePath(List.of(Direction.WEST)) ); } + + @Test + public void 포는_장애물이_1개가_아니면_지나갈수_없다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); + + List blocking = List.of(); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + + assertThat(canJumpTo).isTrue(); + } + + @Test + public void 포은_장애물이_포이면_지나갈수_없다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); + + List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + + assertThat(canJumpTo).isFalse(); + } } diff --git a/src/test/java/strategy/move/ElephantMoveStrategyTest.java b/src/test/java/strategy/move/ElephantMoveStrategyTest.java index 6477538dc4..c324b72deb 100644 --- a/src/test/java/strategy/move/ElephantMoveStrategyTest.java +++ b/src/test/java/strategy/move/ElephantMoveStrategyTest.java @@ -1,5 +1,6 @@ package strategy.move; +import domain.BlockingPieces; import domain.Direction; import domain.MovePath; import domain.Piece; @@ -41,8 +42,9 @@ public class ElephantMoveStrategyTest { public void 상은_장애물이_없으면_지나갈수_있다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blockingPieces = List.of(); - boolean canJumpTo = moveStrategy.canJump(blockingPieces); + List blocking = List.of(); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); assertThat(canJumpTo).isTrue(); } @@ -50,9 +52,9 @@ public class ElephantMoveStrategyTest { @Test public void 상은_장애물이_하나라도_있으면_지나갈수_없다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); - - List blockingPieces = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); - boolean canJumpTo = moveStrategy.canJump(blockingPieces); + List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); assertThat(canJumpTo).isFalse(); } diff --git a/src/test/java/strategy/move/GuardMoveStrategyTest.java b/src/test/java/strategy/move/GuardMoveStrategyTest.java index c8916a739d..fda40996a7 100644 --- a/src/test/java/strategy/move/GuardMoveStrategyTest.java +++ b/src/test/java/strategy/move/GuardMoveStrategyTest.java @@ -1,5 +1,6 @@ package strategy.move; +import domain.BlockingPieces; import domain.Direction; import domain.MovePath; import domain.Piece; @@ -51,8 +52,9 @@ public class GuardMoveStrategyTest { public void 사는_장애물이_없으면_지나갈수_있다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blockingPieces = List.of(); - boolean canJumpTo = moveStrategy.canJump(blockingPieces); + List blocking = List.of(); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); assertThat(canJumpTo).isTrue(); } @@ -61,8 +63,9 @@ public class GuardMoveStrategyTest { public void 사는_장애물이_하나라도_있으면_지나갈수_없다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blockingPieces = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); - boolean canJumpTo = moveStrategy.canJump(blockingPieces); + List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); assertThat(canJumpTo).isFalse(); } diff --git a/src/test/java/strategy/move/HorseMoveStrategyTest.java b/src/test/java/strategy/move/HorseMoveStrategyTest.java index 82fa198ae0..a6c574d6ac 100644 --- a/src/test/java/strategy/move/HorseMoveStrategyTest.java +++ b/src/test/java/strategy/move/HorseMoveStrategyTest.java @@ -1,5 +1,6 @@ package strategy.move; +import domain.BlockingPieces; import domain.Direction; import domain.MovePath; import domain.Piece; @@ -51,8 +52,9 @@ public class HorseMoveStrategyTest { public void 마는_장애물이_없으면_지나갈수_있다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blockingPieces = List.of(); - boolean canJumpTo = moveStrategy.canJump(blockingPieces); + List blocking= List.of(); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); assertThat(canJumpTo).isTrue(); } @@ -61,8 +63,9 @@ public class HorseMoveStrategyTest { public void 마는_장애물이_하나라도_있으면_지나갈수_없다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blockingPieces = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); - boolean canJumpTo = moveStrategy.canJump(blockingPieces); + List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); assertThat(canJumpTo).isFalse(); } diff --git a/src/test/java/strategy/move/KingMoveStrategyTest.java b/src/test/java/strategy/move/KingMoveStrategyTest.java index 9c4861dfd6..a190197a64 100644 --- a/src/test/java/strategy/move/KingMoveStrategyTest.java +++ b/src/test/java/strategy/move/KingMoveStrategyTest.java @@ -1,5 +1,6 @@ package strategy.move; +import domain.BlockingPieces; import domain.Direction; import domain.MovePath; import domain.Piece; @@ -51,8 +52,9 @@ public class KingMoveStrategyTest { public void 왕은_장애물이_없으면_지나갈수_있다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blockingPieces = List.of(); - boolean canJumpTo = moveStrategy.canJump(blockingPieces); + List blocking = List.of(); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); assertThat(canJumpTo).isTrue(); } @@ -61,8 +63,9 @@ public class KingMoveStrategyTest { public void 왕은_장애물이_하나라도_있으면_지나갈수_없다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blockingPieces = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); - boolean canJumpTo = moveStrategy.canJump(blockingPieces); + List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); assertThat(canJumpTo).isFalse(); } diff --git a/src/test/java/strategy/move/PawnMoveStrategyTest.java b/src/test/java/strategy/move/PawnMoveStrategyTest.java index ea72aac8df..83cf43c429 100644 --- a/src/test/java/strategy/move/PawnMoveStrategyTest.java +++ b/src/test/java/strategy/move/PawnMoveStrategyTest.java @@ -1,5 +1,6 @@ package strategy.move; +import domain.BlockingPieces; import domain.Direction; import domain.MovePath; import domain.Piece; @@ -60,8 +61,9 @@ public void setUp() { public void 졸은_장애물이_없으면_지나갈수_있다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blockingPieces = List.of(); - boolean canJumpTo = moveStrategy.canJump(blockingPieces); + List blocking = List.of(); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); assertThat(canJumpTo).isTrue(); } @@ -70,8 +72,9 @@ public void setUp() { public void 졸은_장애물이_하나라도_있으면_지나갈수_없다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blockingPieces = List.of(Piece.of(TeamColor.CHO,PieceType.CANNON)); - boolean canJumpTo = moveStrategy.canJump(blockingPieces); + List blocking = List.of(Piece.of(TeamColor.CHO,PieceType.CANNON)); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); assertThat(canJumpTo).isFalse(); } diff --git a/src/test/java/strategy/move/RookMoveStrategyTest.java b/src/test/java/strategy/move/RookMoveStrategyTest.java index 521e7abe79..97e24d047d 100644 --- a/src/test/java/strategy/move/RookMoveStrategyTest.java +++ b/src/test/java/strategy/move/RookMoveStrategyTest.java @@ -1,5 +1,6 @@ package strategy.move; +import domain.BlockingPieces; import domain.Direction; import domain.MovePath; import domain.Piece; @@ -43,8 +44,9 @@ public class RookMoveStrategyTest { public void 차는_장애물이_없으면_지나갈수_있다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blockingPieces = List.of(); - boolean canJumpTo = moveStrategy.canJump(blockingPieces); + List blocking = List.of(); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); assertThat(canJumpTo).isTrue(); } @@ -53,8 +55,9 @@ public class RookMoveStrategyTest { public void 차는_장애물이_하나라도_있으면_지나갈수_없다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blockingPieces = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); - boolean canJumpTo = moveStrategy.canJump(blockingPieces); + List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); assertThat(canJumpTo).isFalse(); } From 1fb9469141cc0488d236143d4e84f0ec58d3760e Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 19:19:43 +0900 Subject: [PATCH 45/82] =?UTF-8?q?test=20:=20=ED=8F=AC=20=EC=9D=B4=EB=8F=99?= =?UTF-8?q?=20=EC=A0=84=EB=9E=B5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../strategy/move/CannonMoveStrategy.java | 3 - .../strategy/move/CannonMoveStrategyTest.java | 94 +++++++++++++++---- 2 files changed, 78 insertions(+), 19 deletions(-) diff --git a/src/main/java/strategy/move/CannonMoveStrategy.java b/src/main/java/strategy/move/CannonMoveStrategy.java index 76edcbfe70..125cc6cfee 100644 --- a/src/main/java/strategy/move/CannonMoveStrategy.java +++ b/src/main/java/strategy/move/CannonMoveStrategy.java @@ -3,9 +3,6 @@ import domain.BlockingPieces; import domain.Direction; import domain.MovePath; -import domain.Piece; -import domain.Position; -import domain.Route; import domain.TeamColor; import java.util.List; diff --git a/src/test/java/strategy/move/CannonMoveStrategyTest.java b/src/test/java/strategy/move/CannonMoveStrategyTest.java index 18722b5612..510e893df8 100644 --- a/src/test/java/strategy/move/CannonMoveStrategyTest.java +++ b/src/test/java/strategy/move/CannonMoveStrategyTest.java @@ -40,25 +40,87 @@ public class CannonMoveStrategyTest { ); } - @Test - public void 포는_장애물이_1개가_아니면_지나갈수_없다(){ - MoveStrategy moveStrategy = new PawnMoveStrategy(); + @Test + public void 포는_다리가_되는_기물이_하나도_없으면_지나갈수_없다(){ + MoveStrategy moveStrategy = new CannonMoveStrategy(); - List blocking = List.of(); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + List blocking = List.of(); + BlockingPieces blockingPieces = new BlockingPieces(blocking); - assertThat(canJumpTo).isTrue(); - } + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - @Test - public void 포은_장애물이_포이면_지나갈수_없다(){ - MoveStrategy moveStrategy = new PawnMoveStrategy(); + assertThat(canJumpTo).isFalse(); + } + + @Test + public void 포는_다리가_되는_기물이_포이면_지나갈수_없다(){ + MoveStrategy moveStrategy = new CannonMoveStrategy(); + + List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + + assertThat(canJumpTo).isFalse(); + } + + @Test + public void 포는_도착지에_상대방의_포가_있으면_잡을수_없다(){ + MoveStrategy moveStrategy = new CannonMoveStrategy(); + + Piece bridgePawn = Piece.of(TeamColor.CHO, PieceType.PAWN); + Piece targetCannon = Piece.of(TeamColor.HAN, PieceType.CANNON); + + List blocking = List.of(bridgePawn, targetCannon); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + + assertThat(canJumpTo).isFalse(); + } + + @Test + public void 포는_도착지에_같은팀_기물이_있으면_이동할수_없다(){ + MoveStrategy moveStrategy = new CannonMoveStrategy(); + + Piece bridgeRook = Piece.of(TeamColor.HAN, PieceType.ROOK); + Piece targetHorse = Piece.of(TeamColor.CHO, PieceType.HORSE); + + List blocking = List.of(bridgeRook, targetHorse); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + + assertThat(canJumpTo).isFalse(); + } + + + @Test + public void 포는_일반_다리를_넘어_빈칸으로_정상적으로_이동가능하다(){ + MoveStrategy moveStrategy = new CannonMoveStrategy(); + + Piece bridgePawn = Piece.of(TeamColor.CHO, PieceType.PAWN); + + List blocking = List.of(bridgePawn); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + + assertThat(canJumpTo).isTrue(); + } + + @Test + public void 포는_일반_다리를_넘어_도착지에_있는_적군기물을_포획가능하다(){ + MoveStrategy moveStrategy = new CannonMoveStrategy(); + + Piece bridgeHorse = Piece.of(TeamColor.CHO, PieceType.HORSE); + Piece targetRook = Piece.of(TeamColor.HAN, PieceType.ROOK); + + List blocking = List.of(bridgeHorse, targetRook); + BlockingPieces blockingPieces = new BlockingPieces(blocking); - List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isFalse(); + assertThat(canJumpTo).isTrue(); + } } -} From e9467e51ac3fdd0c3ae9fec45d90b5688b250f8f Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 19:22:34 +0900 Subject: [PATCH 46/82] docs: update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 41f956fac0..4a365730e1 100644 --- a/README.md +++ b/README.md @@ -36,11 +36,11 @@ ### 사이클1 구현 내용 -- [ ] [기능구현] 게임에서 사용할 분류 체계 정의 +- [x] [기능구현] 게임에서 사용할 분류 체계 정의 - 전역에서 공통으로 사용하는 값의 종류를 정리 - ex) 팀 구분, 기물 종류, 게임 상태 -- [ ] [기능구현][예외처리] 장기판에서 사용할 좌표 체계를 정의 +- [x] [기능구현][예외처리] 장기판에서 사용할 좌표 체계를 정의 - `Position`, `Direction`, `Route`가 어떤 의미를 가지는지 먼저 확정 - 좌표 범위, 방향 표현 방식, 경로의 시작/끝/중간 위치를 어떻게 다룰지 결정 - [예외처리] 유효하지 않은 좌표 생성 방지 @@ -60,7 +60,7 @@ - 특정 위치에 어떤 기물이 있는지 확인할 수 있도록 - [예외처리] 존재하지 않는 위치 조회 방지 -- [ ] [초기화] 게임 시작 시 장기판을 초기 상태로 세팅 +- [x] [초기화] 게임 시작 시 장기판을 초기 상태로 세팅 - 초기 기물 생성 - 초기 배치 좌표 정의 - 초기 장기판 세팅 @@ -229,4 +229,4 @@ record PieceStartPosition { - 규칙 적용으로 변경한 설계 1곳 - 조건문을 다형성으로 대체한 코드 1곳 - 인터페이스/추상경 클래스를 도입한 이유 -- 새 기물 추가 시 변경 범위 테스트 (가상으로) \ No newline at end of file +- 새 기물 추가 시 변경 범위 테스트 (가상으로) From 31742b9cce289c305c9551f49d160cbb6cc60af8 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 19:25:45 +0900 Subject: [PATCH 47/82] docs: update README.md --- README.md | 53 ++++++++++++++++++++--------------------------------- 1 file changed, 20 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 4a365730e1..5c9f914f06 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ 전체 게임 진행 흐름은 아래 플로우 차트를 기준으로 설계했다. - 보드 세팅 후 턴이 시작된다. -- 현재 턴의 플레이어는 자신의 생존 기물 중 하나를 선택한다. +- 현재 턴의 팀(`TeamColor`)은 자신의 기물 중 하나를 선택한다. - 선택한 기물의 이동 가능 후보 위치를 확인한 뒤 목적지를 선택한다. - 이동 이후 포획 여부, 점수, 장군/외통수 여부를 순서대로 판정한다. - 시간 초과 여부를 확인하고, 종료 조건이 아니라면 현재 장기판 상태를 출력한 뒤 턴을 교체한다. @@ -97,26 +97,23 @@ ### 사이클2 구현 내용 -- [ ] [상태관리] 플레이어가 자신의 팀과 기물 집합을 관리 - - 플레이어는 게임에 참가하는 주체 -> 턴, 승패의 주체 - -- [ ] [상태관리] 플레이어별로 생존 기물과 잡은 기물을 관리할 수 있도록 - - 점수 계산에 필요한 정보 유지 - - 기물 관리 책임은 도메인 단위로 래핑 +- [ ] [상태관리] `TeamColor` 기반으로 현재 턴과 진영 상태를 관리 + - 별도의 Player 객체 없이 현재 턴 팀을 기준으로 게임 흐름을 제어 + - 승패, 점수, 선택 가능 기물 판정도 팀 기준으로 확장 - [ ] [기능구현][상태관리] 포획이 발생했을 때 게임 상태 갱신 - 이동한 목적지에 상대 기물이 있으면 포획으로 처리 - - [ ] [상태관리] 보드 상태와 플레이어의 기물 목록 함께 갱신 + - [ ] [상태관리] `Map` 보드 상태를 기준으로 점유 정보를 갱신 -- [ ] [기능구현] 현재 보드 상태를 기준으로 플레이어의 점수를 계산 - - 시간 초과 시 어떤 기물이 살아 있는지, 잡혔는지 기준으로 점수를 계산 +- [ ] [기능구현] 현재 보드 상태를 기준으로 팀별 점수를 계산 + - 시간 초과 시 `Map`에 남아 있는 기물을 기준으로 점수를 계산 - [ ] [게임흐름] 턴 교체 - - 현재 턴 플레이어 확인 - - 다음 턴 플레이어 확인 + - 현재 턴 `TeamColor` 확인 + - 다음 턴 `TeamColor` 확인 - [ ] [게임흐름][입력][출력] 최소 플레이가 가능한 게임 루프 생성 - - [출력] 현재 턴 플레이어의 기물 목록 출력 +- [출력] 현재 턴 팀의 기물 목록 출력 - [입력] 기물 선택 입력 처리 - [출력] 이동 후보 위치 출력 - [입력] 목적지 선택 입력 처리 @@ -164,7 +161,8 @@ ### JanggiBoard 시나리오 -- Initializer로부터 초기화되었을 때 모든 말들의 위치정보를 가지고 있다. +- 보드 상태는 `Map` 형태로 관리한다. +- Initializer로부터 초기화되었을 때 모든 말들의 위치정보를 가지고 있다. - 기물과 해당 기물의 direction규칙을 받으면, 그 기물이 이동 가능한지 여부를 반환한다. - 범위를 초과하면 '이동'할 수 없다 - 이동하고자 하는 곳에 다른 기물이 있으면 이동할 수 없다 @@ -182,7 +180,7 @@ - 장기 보드와 협력하여 이동 가능한 위치 정보를 받아 루트 정보들을 생성한다. (단, 경로가 막히는 경우는 고려하지 않는다.) ### Initializer 시나리오 -- 게임 초기의 말들의 위치 정보를 가지고 있다. +- 게임 초기의 말들의 위치 정보를 `Map` 형태로 가지고 있다. - ```Java @@ -191,31 +189,20 @@ record PieceStartPosition { } ``` -### Player 시나리오 -- 팀 정보를 가진채로 생성된다. -- 기물저장소를 통해 자신의 기물을 관리한다. - -### PieceStorage - -- 기물과 기물의 현재 상태를 구분하여 저장한다. -- 살아있는 기물을 모아서 반환한다. -- 죽어있는 기물을 모아서 반환한다. -- (후순위) 기물들의 점수를 계산한다. - ### TurnManager 시나리오 -- 현재 턴의 플레이어가 누군지 반환한다. -- 턴이 바뀌면, 현재 플레이어와 다음 플레이어가 스왑된다. -- 턴이 바뀌면, 현재까지 둔 수를 1 올린다. +- 현재 턴의 `TeamColor`가 무엇인지 반환한다. +- 턴이 바뀌면 `CHO`와 `HAN`이 스왑된다. +- 별도의 Player 객체 없이 팀 색상만으로 턴을 관리한다. ### Runner 시나리오 - 기물 선택, 이동 위치 선택 입/출력을 진행한다. - GameStateEnum을 기준으로 게임을 상태에 따라 실행한다. -- Intializer에게 장기판을 세팅하는 함수를 호출한다. -- 플레이어가 정상적인 기물 번호를 선택하고, 정상적인 이동 목적지를 입력하면 JanggiBoard에 움직이는 함수를 호출한다. +- Intializer에게 `Map` 기반 장기판을 세팅하는 함수를 호출한다. +- 현재 턴 팀이 정상적인 기물을 선택하고, 정상적인 이동 목적지를 입력하면 보드 상태를 갱신한다. - TurnManager에게 턴을 교체하는 함수를 호출한다. -- 플레이어가 정상적인 기물 번호를 선택하지 않으면, 예외를 발생하고 기물 선택으로 돌아온다. -- 플레이어가 정상적인 이동 목적지를 입력하지 않으면, 예외를 발생하고 이동 목적지 입력으로 돌아온다. +- 현재 턴 팀이 정상적인 기물 번호를 선택하지 않으면, 예외를 발생하고 기물 선택으로 돌아온다. +- 현재 턴 팀이 정상적인 이동 목적지를 입력하지 않으면, 예외를 발생하고 이동 목적지 입력으로 돌아온다. From 4687be1dfad37d12528bb705e4dd344c36c2f0da Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 19:31:12 +0900 Subject: [PATCH 48/82] =?UTF-8?q?feat:=20canJump=20=EC=B2=B4=ED=81=AC=20?= =?UTF-8?q?=EC=8B=9C=20=EC=95=84=EA=B5=B0=20=EC=97=AC=EB=B6=80=20=EC=B2=B4?= =?UTF-8?q?=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/BlockingPieces.java | 4 ++++ .../java/strategy/move/ElephantMoveStrategy.java | 12 +++++++++--- src/main/java/strategy/move/GuardMoveStrategy.java | 7 ++++++- src/main/java/strategy/move/HorseMoveStrategy.java | 6 ++++++ src/main/java/strategy/move/KingMoveStrategy.java | 8 +++++++- src/main/java/strategy/move/PawnMoveStrategy.java | 8 +++++++- src/main/java/strategy/move/RookMoveStrategy.java | 6 ++++++ 7 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/main/java/domain/BlockingPieces.java b/src/main/java/domain/BlockingPieces.java index 4351545cc0..751de2681b 100644 --- a/src/main/java/domain/BlockingPieces.java +++ b/src/main/java/domain/BlockingPieces.java @@ -39,5 +39,9 @@ public boolean isLastPieceSameTeam(TeamColor myTeam) { public int size() { return pieces.size(); } + + public TeamColor getFirstBlockingTeamColor() { + return pieces.getFirst().getTeamColor(); + } } \ No newline at end of file diff --git a/src/main/java/strategy/move/ElephantMoveStrategy.java b/src/main/java/strategy/move/ElephantMoveStrategy.java index d22178054c..8b16c8734e 100644 --- a/src/main/java/strategy/move/ElephantMoveStrategy.java +++ b/src/main/java/strategy/move/ElephantMoveStrategy.java @@ -30,9 +30,15 @@ public List getPaths(TeamColor teamColor) { @Override public boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam) { if (blockingPieces.size() == 0) { - return true; + return true; } - return false; - } + + if (blockingPieces.size() == 1) { + TeamColor targetTeam = blockingPieces.getFirstBlockingTeamColor(); + return targetTeam != myTeam; + } + + return false; + } } \ No newline at end of file diff --git a/src/main/java/strategy/move/GuardMoveStrategy.java b/src/main/java/strategy/move/GuardMoveStrategy.java index f266344461..6921b0b702 100644 --- a/src/main/java/strategy/move/GuardMoveStrategy.java +++ b/src/main/java/strategy/move/GuardMoveStrategy.java @@ -32,7 +32,12 @@ public boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam) { if (blockingPieces.size() == 0) { return true; } + + if (blockingPieces.size() == 1) { + TeamColor targetTeam = blockingPieces.getFirstBlockingTeamColor(); + return targetTeam != myTeam; + } + return false; } - } diff --git a/src/main/java/strategy/move/HorseMoveStrategy.java b/src/main/java/strategy/move/HorseMoveStrategy.java index c87cc53cc1..b4ffb29665 100644 --- a/src/main/java/strategy/move/HorseMoveStrategy.java +++ b/src/main/java/strategy/move/HorseMoveStrategy.java @@ -31,6 +31,12 @@ public boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam) { if (blockingPieces.size() == 0) { return true; } + + if (blockingPieces.size() == 1) { + TeamColor targetTeam = blockingPieces.getFirstBlockingTeamColor(); + return targetTeam != myTeam; + } + return false; } } \ No newline at end of file diff --git a/src/main/java/strategy/move/KingMoveStrategy.java b/src/main/java/strategy/move/KingMoveStrategy.java index b572c02065..297eb9b877 100644 --- a/src/main/java/strategy/move/KingMoveStrategy.java +++ b/src/main/java/strategy/move/KingMoveStrategy.java @@ -29,9 +29,15 @@ public List getPaths(TeamColor teamColor) { @Override public boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam) { - if (blockingPieces.size()==0) { + if (blockingPieces.size() == 0) { return true; } + + if (blockingPieces.size() == 1) { + TeamColor targetTeam = blockingPieces.getFirstBlockingTeamColor(); + return targetTeam != myTeam; + } + return false; } } diff --git a/src/main/java/strategy/move/PawnMoveStrategy.java b/src/main/java/strategy/move/PawnMoveStrategy.java index 65c190ba30..ce9ad1beaf 100644 --- a/src/main/java/strategy/move/PawnMoveStrategy.java +++ b/src/main/java/strategy/move/PawnMoveStrategy.java @@ -32,9 +32,15 @@ public List getPaths(TeamColor teamColor) { @Override public boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam) { - if (blockingPieces.size()==0) { + if (blockingPieces.size() == 0) { return true; } + + if (blockingPieces.size() == 1) { + TeamColor targetTeam = blockingPieces.getFirstBlockingTeamColor(); + return targetTeam != myTeam; + } + return false; } diff --git a/src/main/java/strategy/move/RookMoveStrategy.java b/src/main/java/strategy/move/RookMoveStrategy.java index 67fed4c48d..03db490c7c 100644 --- a/src/main/java/strategy/move/RookMoveStrategy.java +++ b/src/main/java/strategy/move/RookMoveStrategy.java @@ -26,6 +26,12 @@ public boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam) { if (blockingPieces.size() == 0) { return true; } + + if (blockingPieces.size() == 1) { + TeamColor targetTeam = blockingPieces.getFirstBlockingTeamColor(); + return targetTeam != myTeam; + } + return false; } From 8ac16d20b98120bdc53f7f122c7718f6f5ccd099 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 19:43:43 +0900 Subject: [PATCH 49/82] test : create pawn makeRoute test code --- src/main/java/strategy/move/MoveStrategy.java | 2 -- .../strategy/move/PawnMoveStrategyTest.java | 26 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/main/java/strategy/move/MoveStrategy.java b/src/main/java/strategy/move/MoveStrategy.java index 33d6d7dd1d..ab382f725b 100644 --- a/src/main/java/strategy/move/MoveStrategy.java +++ b/src/main/java/strategy/move/MoveStrategy.java @@ -8,7 +8,6 @@ import java.util.ArrayList; import java.util.List; import domain.Route; -import domain.Piece; public interface MoveStrategy { @@ -39,5 +38,4 @@ default List makeRoutes(Position curPos, TeamColor teamColor) { boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam); - } diff --git a/src/test/java/strategy/move/PawnMoveStrategyTest.java b/src/test/java/strategy/move/PawnMoveStrategyTest.java index 83cf43c429..571109235c 100644 --- a/src/test/java/strategy/move/PawnMoveStrategyTest.java +++ b/src/test/java/strategy/move/PawnMoveStrategyTest.java @@ -78,4 +78,30 @@ public void setUp() { assertThat(canJumpTo).isFalse(); } + + @Test + public void 초나라_졸은_현재위치와_이동방향을_기반으로_이동가능한_좌표들_구한다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); + Position curPos = Position.of(3,4); + + List possibleRoutes = moveStrategy.makeRoutes(curPos, TeamColor.CHO); + assertThat(possibleRoutes).containsExactlyInAnyOrder( + new Route(curPos,Position.of(2,4),List.of()), + new Route(curPos,Position.of(3,5),List.of()), + new Route(curPos,Position.of(3,3),List.of()) + ); + } + + @Test + public void 한나라_졸은_현재위치와_이동방향을_기반으로_이동가능한_좌표들_구한다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); + Position curPos = Position.of(3,4); + + List possibleRoutes = moveStrategy.makeRoutes(curPos, TeamColor.HAN); + assertThat(possibleRoutes).containsExactlyInAnyOrder( + new Route(curPos,Position.of(4,4),List.of()), + new Route(curPos,Position.of(3,5),List.of()), + new Route(curPos,Position.of(3,3),List.of()) + ); + } } From 0336f238683672d3988703df11e5f43fc2a12bea Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 19:45:58 +0900 Subject: [PATCH 50/82] =?UTF-8?q?refactor:=20PawnMoveStrategyTest=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BC=80=EC=9D=B4=EC=8A=A4=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 --- .../strategy/move/PawnMoveStrategyTest.java | 34 +++---------------- 1 file changed, 5 insertions(+), 29 deletions(-) diff --git a/src/test/java/strategy/move/PawnMoveStrategyTest.java b/src/test/java/strategy/move/PawnMoveStrategyTest.java index 571109235c..fe040f42ec 100644 --- a/src/test/java/strategy/move/PawnMoveStrategyTest.java +++ b/src/test/java/strategy/move/PawnMoveStrategyTest.java @@ -36,11 +36,11 @@ public void setUp() { @Test public void 한나라_졸은_남동서로_이동_가능하다() { MoveStrategy moveStrategy = new PawnMoveStrategy(); - List movePathList = moveStrategy.getPaths(TeamColor.HAN); - assertThat(movePathList).contains(new MovePath(List.of(Direction.SOUTH))); - assertThat(movePathList).contains(new MovePath(List.of(Direction.WEST))); - assertThat(movePathList).contains(new MovePath(List.of(Direction.EAST))); - assertThat(movePathList).doesNotContain(new MovePath(List.of(Direction.NORTH))); + List movePaths = moveStrategy.getPaths(TeamColor.HAN); + assertThat(movePaths).contains(new MovePath(List.of(Direction.SOUTH))); + assertThat(movePaths).contains(new MovePath(List.of(Direction.WEST))); + assertThat(movePaths).contains(new MovePath(List.of(Direction.EAST))); + assertThat(movePaths).doesNotContain(new MovePath(List.of(Direction.NORTH))); } @@ -79,29 +79,5 @@ public void setUp() { assertThat(canJumpTo).isFalse(); } - @Test - public void 초나라_졸은_현재위치와_이동방향을_기반으로_이동가능한_좌표들_구한다(){ - MoveStrategy moveStrategy = new PawnMoveStrategy(); - Position curPos = Position.of(3,4); - - List possibleRoutes = moveStrategy.makeRoutes(curPos, TeamColor.CHO); - assertThat(possibleRoutes).containsExactlyInAnyOrder( - new Route(curPos,Position.of(2,4),List.of()), - new Route(curPos,Position.of(3,5),List.of()), - new Route(curPos,Position.of(3,3),List.of()) - ); - } - - @Test - public void 한나라_졸은_현재위치와_이동방향을_기반으로_이동가능한_좌표들_구한다(){ - MoveStrategy moveStrategy = new PawnMoveStrategy(); - Position curPos = Position.of(3,4); - List possibleRoutes = moveStrategy.makeRoutes(curPos, TeamColor.HAN); - assertThat(possibleRoutes).containsExactlyInAnyOrder( - new Route(curPos,Position.of(4,4),List.of()), - new Route(curPos,Position.of(3,5),List.of()), - new Route(curPos,Position.of(3,3),List.of()) - ); - } } From cd289ebfc1339293cbd8715c9de5735e3f06f64e Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 19:52:21 +0900 Subject: [PATCH 51/82] =?UTF-8?q?test=20:=20=EC=B0=A8,=ED=8F=AC=EB=A5=BC?= =?UTF-8?q?=20=EC=A0=9C=EC=99=B8=ED=95=9C=20=EA=B8=B0=EB=AC=BC=EB=93=A4?= =?UTF-8?q?=EC=9D=98=20makeRoutes=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BC=80=EC=9D=B4=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 --- .../move/ElephantMoveStrategyTest.java | 23 +++++++++++++++++ .../strategy/move/GuardMoveStrategyTest.java | 22 ++++++++++++++++ .../strategy/move/HorseMoveStrategyTest.java | 25 +++++++++++++++++++ .../strategy/move/KingMoveStrategyTest.java | 24 ++++++++++++++++++ .../strategy/move/PawnMoveStrategyTest.java | 13 ++++++++++ 5 files changed, 107 insertions(+) diff --git a/src/test/java/strategy/move/ElephantMoveStrategyTest.java b/src/test/java/strategy/move/ElephantMoveStrategyTest.java index c324b72deb..15e1937998 100644 --- a/src/test/java/strategy/move/ElephantMoveStrategyTest.java +++ b/src/test/java/strategy/move/ElephantMoveStrategyTest.java @@ -5,6 +5,8 @@ import domain.MovePath; import domain.Piece; import domain.PieceType; +import domain.Position; +import domain.Route; import domain.TeamColor; import java.util.List; import org.junit.jupiter.api.Test; @@ -58,4 +60,25 @@ public class ElephantMoveStrategyTest { assertThat(canJumpTo).isFalse(); } + + @Test + public void 상이_정상적으로_진행경로_좌표를_안다() { + Position curPos = Position.of(4, 4); + MoveStrategy moveStrategy = new ElephantMoveStrategy(); + + List routes = moveStrategy.makeRoutes(curPos, TeamColor.CHO); + assertThat(routes).containsExactlyInAnyOrder( + new Route(curPos, Position.of(1, 2), List.of(Position.of(3, 4), Position.of(2, 3))), + new Route(curPos, Position.of(1, 6), List.of(Position.of(3, 4), Position.of(2, 5))), + + new Route(curPos, Position.of(7, 2), List.of(Position.of(5, 4), Position.of(6, 3))), + new Route(curPos, Position.of(7, 6), List.of(Position.of(5, 4), Position.of(6, 5))), + + new Route(curPos, Position.of(2, 1), List.of(Position.of(4, 3), Position.of(3, 2))), + new Route(curPos, Position.of(6, 1), List.of(Position.of(4, 3), Position.of(5, 2))), + + new Route(curPos, Position.of(2, 7), List.of(Position.of(4, 5), Position.of(3, 6))), + new Route(curPos, Position.of(6, 7), List.of(Position.of(4, 5), Position.of(5, 6))) + ); + } } \ No newline at end of file diff --git a/src/test/java/strategy/move/GuardMoveStrategyTest.java b/src/test/java/strategy/move/GuardMoveStrategyTest.java index fda40996a7..05e75d7c89 100644 --- a/src/test/java/strategy/move/GuardMoveStrategyTest.java +++ b/src/test/java/strategy/move/GuardMoveStrategyTest.java @@ -5,6 +5,8 @@ import domain.MovePath; import domain.Piece; import domain.PieceType; +import domain.Position; +import domain.Route; import domain.TeamColor; import java.util.List; import org.junit.jupiter.api.Test; @@ -69,5 +71,25 @@ public class GuardMoveStrategyTest { assertThat(canJumpTo).isFalse(); } + + @Test + public void 왕이_정상적으로_진행경로_좌표를_안다() { + Position curPos = Position.of(1, 4); + MoveStrategy moveStrategy = new GuardMoveStrategy(); + + List routes = moveStrategy.makeRoutes(curPos, TeamColor.CHO); + assertThat(routes).containsExactlyInAnyOrder( + + new Route(curPos, Position.of(0, 4), List.of()), + new Route(curPos, Position.of(2, 4), List.of()), + new Route(curPos, Position.of(1, 3), List.of()), + new Route(curPos, Position.of(1, 5), List.of()), + + new Route(curPos, Position.of(0, 3), List.of()), + new Route(curPos, Position.of(0, 5), List.of()), + new Route(curPos, Position.of(2, 3), List.of()), + new Route(curPos, Position.of(2, 5), List.of()) + ); + } } diff --git a/src/test/java/strategy/move/HorseMoveStrategyTest.java b/src/test/java/strategy/move/HorseMoveStrategyTest.java index a6c574d6ac..5ad599785b 100644 --- a/src/test/java/strategy/move/HorseMoveStrategyTest.java +++ b/src/test/java/strategy/move/HorseMoveStrategyTest.java @@ -5,6 +5,8 @@ import domain.MovePath; import domain.Piece; import domain.PieceType; +import domain.Position; +import domain.Route; import domain.TeamColor; import java.util.List; import org.junit.jupiter.api.Test; @@ -69,4 +71,27 @@ public class HorseMoveStrategyTest { assertThat(canJumpTo).isFalse(); } + + @Test + public void 마가_정상적으로_진행경로_좌표를_안다() { + // 중앙인 (4, 4)에 있다고 가정 (8방향 모두 이동 가능한 위치) + Position curPos = Position.of(4, 4); + MoveStrategy moveStrategy = new HorseMoveStrategy(); + + List routes = moveStrategy.makeRoutes(curPos, TeamColor.CHO); + assertThat(routes).containsExactlyInAnyOrder( + + new Route(curPos, Position.of(2, 3), List.of(Position.of(3, 4))), + new Route(curPos, Position.of(2, 5), List.of(Position.of(3, 4))), + + new Route(curPos, Position.of(6, 3), List.of(Position.of(5, 4))), + new Route(curPos, Position.of(6, 5), List.of(Position.of(5, 4))), + + new Route(curPos, Position.of(3, 2), List.of(Position.of(4, 3))), + new Route(curPos, Position.of(5, 2), List.of(Position.of(4, 3))), + + new Route(curPos, Position.of(3, 6), List.of(Position.of(4, 5))), + new Route(curPos, Position.of(5, 6), List.of(Position.of(4, 5))) + ); + } } \ No newline at end of file diff --git a/src/test/java/strategy/move/KingMoveStrategyTest.java b/src/test/java/strategy/move/KingMoveStrategyTest.java index a190197a64..25724c6095 100644 --- a/src/test/java/strategy/move/KingMoveStrategyTest.java +++ b/src/test/java/strategy/move/KingMoveStrategyTest.java @@ -5,6 +5,8 @@ import domain.MovePath; import domain.Piece; import domain.PieceType; +import domain.Position; +import domain.Route; import domain.TeamColor; import java.util.List; import org.junit.jupiter.api.Test; @@ -69,5 +71,27 @@ public class KingMoveStrategyTest { assertThat(canJumpTo).isFalse(); } + + @Test + public void 왕이_정상적으로_진행경로_좌표를_안다() { + + Position curPos = Position.of(1, 4); + MoveStrategy moveStrategy = new KingMoveStrategy(); + + List routes = moveStrategy.makeRoutes(curPos, TeamColor.CHO); + assertThat(routes).containsExactlyInAnyOrder( + + new Route(curPos, Position.of(0, 4), List.of()), + new Route(curPos, Position.of(2, 4), List.of()), + new Route(curPos, Position.of(1, 3), List.of()), + new Route(curPos, Position.of(1, 5), List.of()), + + new Route(curPos, Position.of(0, 3), List.of()), + new Route(curPos, Position.of(0, 5), List.of()), + new Route(curPos, Position.of(2, 3), List.of()), + new Route(curPos, Position.of(2, 5), List.of()) + ); + } + } diff --git a/src/test/java/strategy/move/PawnMoveStrategyTest.java b/src/test/java/strategy/move/PawnMoveStrategyTest.java index fe040f42ec..49e09299a2 100644 --- a/src/test/java/strategy/move/PawnMoveStrategyTest.java +++ b/src/test/java/strategy/move/PawnMoveStrategyTest.java @@ -57,6 +57,19 @@ public void setUp() { ); } + @Test + public void 한나라_졸은_현재위치와_이동방향을_기반으로_이동가능한_좌표들_구한다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); + Position curPos = Position.of(3,4); + + List possibleRoutes = moveStrategy.makeRoutes(curPos, TeamColor.HAN); + assertThat(possibleRoutes).containsExactlyInAnyOrder( + new Route(curPos,Position.of(4,4),List.of()), + new Route(curPos,Position.of(3,5),List.of()), + new Route(curPos,Position.of(3,3),List.of()) + ); + } + @Test public void 졸은_장애물이_없으면_지나갈수_있다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); From b7c69eb2afb7e2ebd3d1ef57857efa63ed60611e Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 20:04:32 +0900 Subject: [PATCH 52/82] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=EB=93=A4=EC=97=90=20Nested=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/test/java/InitializerTest.java | 110 ++++++------- src/test/java/domain/ColumnTest.java | 33 ++-- src/test/java/domain/RowTest.java | 36 +++-- src/test/java/domain/TurnManagerTest.java | 23 +-- .../InitialFormationStrategyTest.java | 89 +++++------ .../formation/InnerFormationStrategyTest.java | 59 +++---- .../formation/LeftFormationStrategyTest.java | 47 +++--- .../formation/OuterFormationStrategyTest.java | 55 ++++--- .../formation/RightFormationStrategyTest.java | 47 +++--- .../strategy/move/CannonMoveStrategyTest.java | 66 ++++---- .../move/ElephantMoveStrategyTest.java | 126 ++++++++------- .../strategy/move/GuardMoveStrategyTest.java | 144 +++++++++-------- .../strategy/move/HorseMoveStrategyTest.java | 148 +++++++++--------- .../strategy/move/KingMoveStrategyTest.java | 146 ++++++++--------- .../strategy/move/PawnMoveStrategyTest.java | 129 +++++++-------- .../strategy/move/RookMoveStrategyTest.java | 84 +++++----- 16 files changed, 695 insertions(+), 647 deletions(-) diff --git a/src/test/java/InitializerTest.java b/src/test/java/InitializerTest.java index e255e6ac79..ea306d01e3 100644 --- a/src/test/java/InitializerTest.java +++ b/src/test/java/InitializerTest.java @@ -4,6 +4,7 @@ import domain.TeamColor; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -27,59 +28,62 @@ public void setUp(){ } - @Test - void 초나라_한나라_전략을_주입받아_총_32개의_기물이_세팅된_초기_장기판을_반환한다() { - assertThat(initialGameState.boardState()).hasSize(32); - assertThat(initialGameState.boardState().get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); - assertThat(initialGameState.boardState().get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + @Nested + class 초기화 { + @Test + void 초나라_한나라_전략을_주입받아_총_32개의_기물이_세팅된_초기_장기판을_반환한다() { + assertThat(initialGameState.boardState()).hasSize(32); + assertThat(initialGameState.boardState().get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); + assertThat(initialGameState.boardState().get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + } } - @Test - void 초나라_기물_리스트를_생성한다() { - // 16개 생성됐는지 - assertThat(initialGameState.choPieces()).hasSize(16); - // 기물 마다 개수를 테스트 : 졸5, 상2, 마2, 포2, 차2, 사2, 궁1 - assertThat( - initialGameState.choPieces().stream() - .filter(p -> p.getTeamColor() == TeamColor.CHO) - .filter(p -> p.getPieceType() == PieceType.ELEPHANT) - ).hasSize(2); - - assertThat( - initialGameState.choPieces().stream() - .filter(p -> p.getTeamColor() == TeamColor.CHO) - .filter(p -> p.getPieceType() == PieceType.HORSE) - ).hasSize(2); - - assertThat( - initialGameState.choPieces().stream() - .filter(p -> p.getTeamColor() == TeamColor.CHO) - .filter(p -> p.getPieceType() == PieceType.CANNON) - ).hasSize(2); - - assertThat( - initialGameState.choPieces().stream() - .filter(p -> p.getTeamColor() == TeamColor.CHO) - .filter(p -> p.getPieceType() == PieceType.ROOK) - ).hasSize(2); - - assertThat( - initialGameState.choPieces().stream() - .filter(p -> p.getTeamColor() == TeamColor.CHO) - .filter(p -> p.getPieceType() == PieceType.GUARD) - ).hasSize(2); - - assertThat( - initialGameState.choPieces().stream() - .filter(p -> p.getTeamColor() == TeamColor.CHO) - .filter(p -> p.getPieceType() == PieceType.PAWN) - ).hasSize(5); - - assertThat( - initialGameState.choPieces().stream() - .filter(p -> p.getTeamColor() == TeamColor.CHO) - .filter(p -> p.getPieceType() == PieceType.KING) - ).hasSize(1); - + @Nested + class 기물목록 { + @Test + void 초나라_기물_리스트를_생성한다() { + assertThat(initialGameState.choPieces()).hasSize(16); + assertThat( + initialGameState.choPieces().stream() + .filter(p -> p.getTeamColor() == TeamColor.CHO) + .filter(p -> p.getPieceType() == PieceType.ELEPHANT) + ).hasSize(2); + + assertThat( + initialGameState.choPieces().stream() + .filter(p -> p.getTeamColor() == TeamColor.CHO) + .filter(p -> p.getPieceType() == PieceType.HORSE) + ).hasSize(2); + + assertThat( + initialGameState.choPieces().stream() + .filter(p -> p.getTeamColor() == TeamColor.CHO) + .filter(p -> p.getPieceType() == PieceType.CANNON) + ).hasSize(2); + + assertThat( + initialGameState.choPieces().stream() + .filter(p -> p.getTeamColor() == TeamColor.CHO) + .filter(p -> p.getPieceType() == PieceType.ROOK) + ).hasSize(2); + + assertThat( + initialGameState.choPieces().stream() + .filter(p -> p.getTeamColor() == TeamColor.CHO) + .filter(p -> p.getPieceType() == PieceType.GUARD) + ).hasSize(2); + + assertThat( + initialGameState.choPieces().stream() + .filter(p -> p.getTeamColor() == TeamColor.CHO) + .filter(p -> p.getPieceType() == PieceType.PAWN) + ).hasSize(5); + + assertThat( + initialGameState.choPieces().stream() + .filter(p -> p.getTeamColor() == TeamColor.CHO) + .filter(p -> p.getPieceType() == PieceType.KING) + ).hasSize(1); + } } -} \ No newline at end of file +} diff --git a/src/test/java/domain/ColumnTest.java b/src/test/java/domain/ColumnTest.java index e9ce9eb7e0..de7269bbd9 100644 --- a/src/test/java/domain/ColumnTest.java +++ b/src/test/java/domain/ColumnTest.java @@ -2,29 +2,32 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; public class ColumnTest { - @Test - void 유효한_값으로_행_객체가_생성된_경우() { - //given - int input = 3; - //when - Column column = new Column(input); + @Nested + class 생성 { + @Test + void 유효한_값으로_행_객체가_생성된_경우() { + int input = 3; - //then - assertThat(column.value()).isEqualTo(3); + Column column = new Column(input); + assertThat(column.value()).isEqualTo(3); + } } + @Nested + class 예외 { + @Test + void 값이_최댓값을_초과하면_예외를_발행한다() { + int input = 19; - @Test - void 값이_최댓값을_초과하면_예외를_발행한다() { - int input = 19; - - assertThatThrownBy(() -> new Column(input)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("열의 최대 값은 9입니다."); + assertThatThrownBy(() -> new Column(input)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("열의 최대 값은 9입니다."); + } } } diff --git a/src/test/java/domain/RowTest.java b/src/test/java/domain/RowTest.java index 4d180df538..0d1abec1d7 100644 --- a/src/test/java/domain/RowTest.java +++ b/src/test/java/domain/RowTest.java @@ -2,30 +2,32 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; class RowTest { - @Test - void 유효한_값으로_행_객체가_생성된_경우() { - //given - int input = 3; - //when - Row row = new Row(input); + @Nested + class 생성 { + @Test + void 유효한_값으로_행_객체가_생성된_경우() { + int input = 3; - //then - assertThat(row.value()).isEqualTo(3); + Row row = new Row(input); + assertThat(row.value()).isEqualTo(3); + } } + @Nested + class 예외 { + @Test + void 값이_최댓값을_초과하면_예외를_발행한다() { + int input = 19; - @Test - void 값이_최댓값을_초과하면_예외를_발행한다() { - int input = 19; - - assertThatThrownBy(() -> new Row(input)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("행의 최대 값은 8입니다."); + assertThatThrownBy(() -> new Row(input)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("행의 최대 값은 8입니다."); + } } - -} \ No newline at end of file +} diff --git a/src/test/java/domain/TurnManagerTest.java b/src/test/java/domain/TurnManagerTest.java index f4627bfc61..7f8ac763e7 100644 --- a/src/test/java/domain/TurnManagerTest.java +++ b/src/test/java/domain/TurnManagerTest.java @@ -1,6 +1,7 @@ package domain; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -13,16 +14,20 @@ public void setUp(){ turnManager = new TurnManager(); } - @Test - public void 현재_턴이_누구인지_반환한다() { - assertThat(turnManager.getCurrentTurn()).isEqualTo(TeamColor.CHO); - + @Nested + class 현재턴 { + @Test + public void 현재_턴이_누구인지_반환한다() { + assertThat(turnManager.getCurrentTurn()).isEqualTo(TeamColor.CHO); + } } - @Test - public void 턴이_바뀌면_반대팀이_현재_턴이_된다() { - turnManager.progressTurn(); - assertThat(turnManager.getCurrentTurn()).isEqualTo(TeamColor.HAN); - + @Nested + class 턴진행 { + @Test + public void 턴이_바뀌면_반대팀이_현재_턴이_된다() { + turnManager.progressTurn(); + assertThat(turnManager.getCurrentTurn()).isEqualTo(TeamColor.HAN); + } } } diff --git a/src/test/java/strategy/formation/InitialFormationStrategyTest.java b/src/test/java/strategy/formation/InitialFormationStrategyTest.java index 916d8c6406..c51c8fabfc 100644 --- a/src/test/java/strategy/formation/InitialFormationStrategyTest.java +++ b/src/test/java/strategy/formation/InitialFormationStrategyTest.java @@ -5,6 +5,7 @@ import domain.Position; import domain.TeamColor; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import java.util.Map; @@ -20,60 +21,44 @@ void setUp() { strategy = new TestStrategy(); } - @Test - void 한나라_고정_기물들이_올바른_위치에_배치된다() { - Map result = strategy.setUpPieces(TeamColor.HAN); - - assertThat(result).hasSize(12); - - // 한나라는 위쪽 진영 (y = 0 ~ 3) - // 1. 차 - assertThat(result.get(Position.of(0, 0)).getPieceType()).isEqualTo(PieceType.ROOK); - assertThat(result.get(Position.of(8, 0)).getPieceType()).isEqualTo(PieceType.ROOK); - - // 2. 사 - assertThat(result.get(Position.of(3, 0)).getPieceType()).isEqualTo(PieceType.GUARD); - assertThat(result.get(Position.of(5, 0)).getPieceType()).isEqualTo(PieceType.GUARD); - - // 3. 궁 - assertThat(result.get(Position.of(4, 1)).getPieceType()).isEqualTo(PieceType.KING); - - // 4. 포 - assertThat(result.get(Position.of(1, 2)).getPieceType()).isEqualTo(PieceType.CANNON); - assertThat(result.get(Position.of(7, 2)).getPieceType()).isEqualTo(PieceType.CANNON); - - // 5. 병 - assertThat(result.get(Position.of(0, 3)).getPieceType()).isEqualTo(PieceType.PAWN); - assertThat(result.get(Position.of(4, 3)).getPieceType()).isEqualTo(PieceType.PAWN); - assertThat(result.get(Position.of(8, 3)).getPieceType()).isEqualTo(PieceType.PAWN); + @Nested + class 한나라 { + @Test + void 고정_기물들이_올바른_위치에_배치된다() { + Map result = strategy.setUpPieces(TeamColor.HAN); + + assertThat(result).hasSize(12); + assertThat(result.get(Position.of(0, 0)).getPieceType()).isEqualTo(PieceType.ROOK); + assertThat(result.get(Position.of(8, 0)).getPieceType()).isEqualTo(PieceType.ROOK); + assertThat(result.get(Position.of(3, 0)).getPieceType()).isEqualTo(PieceType.GUARD); + assertThat(result.get(Position.of(5, 0)).getPieceType()).isEqualTo(PieceType.GUARD); + assertThat(result.get(Position.of(4, 1)).getPieceType()).isEqualTo(PieceType.KING); + assertThat(result.get(Position.of(1, 2)).getPieceType()).isEqualTo(PieceType.CANNON); + assertThat(result.get(Position.of(7, 2)).getPieceType()).isEqualTo(PieceType.CANNON); + assertThat(result.get(Position.of(0, 3)).getPieceType()).isEqualTo(PieceType.PAWN); + assertThat(result.get(Position.of(4, 3)).getPieceType()).isEqualTo(PieceType.PAWN); + assertThat(result.get(Position.of(8, 3)).getPieceType()).isEqualTo(PieceType.PAWN); + } } - @Test - void 초나라_고정_기물들이_올바른_위치에_배치된다() { - Map result = strategy.setUpPieces(TeamColor.CHO); - - assertThat(result).hasSize(12); - - // 초나라는 아래쪽 진영 (y = 6 ~ 9) - // 1. 차 - assertThat(result.get(Position.of(0, 9)).getPieceType()).isEqualTo(PieceType.ROOK); - assertThat(result.get(Position.of(8, 9)).getPieceType()).isEqualTo(PieceType.ROOK); - - // 2. 사 - assertThat(result.get(Position.of(3, 9)).getPieceType()).isEqualTo(PieceType.GUARD); - assertThat(result.get(Position.of(5, 9)).getPieceType()).isEqualTo(PieceType.GUARD); - - // 3. 궁 - assertThat(result.get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); - - // 4. 포 - assertThat(result.get(Position.of(1, 7)).getPieceType()).isEqualTo(PieceType.CANNON); - assertThat(result.get(Position.of(7, 7)).getPieceType()).isEqualTo(PieceType.CANNON); - - // 5. 졸 - assertThat(result.get(Position.of(0, 6)).getPieceType()).isEqualTo(PieceType.PAWN); - assertThat(result.get(Position.of(4, 6)).getPieceType()).isEqualTo(PieceType.PAWN); - assertThat(result.get(Position.of(8, 6)).getPieceType()).isEqualTo(PieceType.PAWN); + @Nested + class 초나라 { + @Test + void 고정_기물들이_올바른_위치에_배치된다() { + Map result = strategy.setUpPieces(TeamColor.CHO); + + assertThat(result).hasSize(12); + assertThat(result.get(Position.of(0, 9)).getPieceType()).isEqualTo(PieceType.ROOK); + assertThat(result.get(Position.of(8, 9)).getPieceType()).isEqualTo(PieceType.ROOK); + assertThat(result.get(Position.of(3, 9)).getPieceType()).isEqualTo(PieceType.GUARD); + assertThat(result.get(Position.of(5, 9)).getPieceType()).isEqualTo(PieceType.GUARD); + assertThat(result.get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); + assertThat(result.get(Position.of(1, 7)).getPieceType()).isEqualTo(PieceType.CANNON); + assertThat(result.get(Position.of(7, 7)).getPieceType()).isEqualTo(PieceType.CANNON); + assertThat(result.get(Position.of(0, 6)).getPieceType()).isEqualTo(PieceType.PAWN); + assertThat(result.get(Position.of(4, 6)).getPieceType()).isEqualTo(PieceType.PAWN); + assertThat(result.get(Position.of(8, 6)).getPieceType()).isEqualTo(PieceType.PAWN); + } } } diff --git a/src/test/java/strategy/formation/InnerFormationStrategyTest.java b/src/test/java/strategy/formation/InnerFormationStrategyTest.java index cd89e495e6..e965b69f7f 100644 --- a/src/test/java/strategy/formation/InnerFormationStrategyTest.java +++ b/src/test/java/strategy/formation/InnerFormationStrategyTest.java @@ -6,6 +6,7 @@ import domain.TeamColor; import java.util.Map; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -19,41 +20,33 @@ public void setUp() { } - @Test - public void 한나라_안상차림일_때_마와_상의_좌표가_올바르다() { - // given & when: 한나라(TeamColor.HAN)의 전체 초기 배치 맵을 반환받는다. - Map formation = initialFormationStrategy.setUpPieces(TeamColor.HAN); + @Nested + class 한나라 { + @Test + public void 안상차림일_때_마와_상의_좌표가_올바르다() { + Map formation = initialFormationStrategy.setUpPieces(TeamColor.HAN); - // then: 반환된 기물이 정확히 16개인지 확인 - assertThat(formation.size()).isEqualTo(16); - - // 상좌표 검증 - 한상1(2,0), 한상2(6,0) - // (장기판 맨 윗줄이 y=0 이라고 가정) - assertThat(formation.get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(6, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - - // 마좌표 검증 - 한마1(1,0), 한마2(7,0) - assertThat(formation.get(Position.of(1, 0)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(7, 0)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(4, 1)).getPieceType()).isEqualTo(PieceType.KING); + assertThat(formation.size()).isEqualTo(16); + assertThat(formation.get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(6, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(1, 0)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(7, 0)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(4, 1)).getPieceType()).isEqualTo(PieceType.KING); + } } - @Test - public void 초나라_안상차림일_때_마와_상의_좌표가_올바르다() { - // given & when: 초나라(TeamColor.CHO)의 전체 초기 배치 맵을 반환받는다. - Map formation = initialFormationStrategy.setUpPieces(TeamColor.CHO); - - // then: 반환된 기물이 정확히 16개인지 확인 - assertThat(formation.size()).isEqualTo(16); - - // 상좌표 검증 - 초상1(2,9), 초상2(6,9) - // (장기판 맨 아랫줄이 y=9 라고 가정) - assertThat(formation.get(Position.of(2, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(6, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - - // 마좌표 검증 - 초마1(1,9), 초마2(7,9) - assertThat(formation.get(Position.of(7, 9)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(1, 9)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); + @Nested + class 초나라 { + @Test + public void 안상차림일_때_마와_상의_좌표가_올바르다() { + Map formation = initialFormationStrategy.setUpPieces(TeamColor.CHO); + + assertThat(formation.size()).isEqualTo(16); + assertThat(formation.get(Position.of(2, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(6, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(7, 9)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(1, 9)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); + } } } diff --git a/src/test/java/strategy/formation/LeftFormationStrategyTest.java b/src/test/java/strategy/formation/LeftFormationStrategyTest.java index be8108532a..981fab93b2 100644 --- a/src/test/java/strategy/formation/LeftFormationStrategyTest.java +++ b/src/test/java/strategy/formation/LeftFormationStrategyTest.java @@ -6,6 +6,7 @@ import domain.TeamColor; import java.util.Map; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -19,27 +20,33 @@ public void setUp() { initialFormationStrategy = new LeftFormationStrategy(); } - @Test - public void 한나라_좌상차림일_때_마와_상의_좌표가_올바르다() { - Map formation = initialFormationStrategy.setUpPieces(TeamColor.HAN); - - assertThat(formation.size()).isEqualTo(16); - assertThat(formation.get(Position.of(1, 0)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(6, 0)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(7, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(4, 1)).getPieceType()).isEqualTo(PieceType.KING); + @Nested + class 한나라 { + @Test + public void 좌상차림일_때_마와_상의_좌표가_올바르다() { + Map formation = initialFormationStrategy.setUpPieces(TeamColor.HAN); + + assertThat(formation.size()).isEqualTo(16); + assertThat(formation.get(Position.of(1, 0)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(6, 0)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(7, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(4, 1)).getPieceType()).isEqualTo(PieceType.KING); + } } - @Test - public void 초나라_좌상차림일_때_마와_상의_좌표가_올바르다() { - Map formation = initialFormationStrategy.setUpPieces(TeamColor.CHO); - - assertThat(formation.size()).isEqualTo(16); - assertThat(formation.get(Position.of(1, 9)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(2, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(6, 9)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(7, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); + @Nested + class 초나라 { + @Test + public void 좌상차림일_때_마와_상의_좌표가_올바르다() { + Map formation = initialFormationStrategy.setUpPieces(TeamColor.CHO); + + assertThat(formation.size()).isEqualTo(16); + assertThat(formation.get(Position.of(1, 9)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(2, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(6, 9)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(7, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); + } } } diff --git a/src/test/java/strategy/formation/OuterFormationStrategyTest.java b/src/test/java/strategy/formation/OuterFormationStrategyTest.java index 43c2cdd46c..f3fc38bb7f 100644 --- a/src/test/java/strategy/formation/OuterFormationStrategyTest.java +++ b/src/test/java/strategy/formation/OuterFormationStrategyTest.java @@ -6,6 +6,7 @@ import domain.TeamColor; import java.util.Map; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -18,35 +19,33 @@ public void setUp() { initialFormationStrategy = new OuterFormationStrategy(); } - @Test - public void 한나라_바깥상차림일_때_마와_상의_좌표가_올바르다() { - Map formation = initialFormationStrategy.setUpPieces(TeamColor.HAN); - - assertThat(formation.size()).isEqualTo(16); - - // 상좌표 검증 - 한상1(1,0), 한상2(7,0) - assertThat(formation.get(Position.of(1, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(7, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - - // 마좌표 검증 - 한마1(2,0), 한마2(6,0) - assertThat(formation.get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(6, 0)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(4, 1)).getPieceType()).isEqualTo(PieceType.KING); + @Nested + class 한나라 { + @Test + public void 바깥상차림일_때_마와_상의_좌표가_올바르다() { + Map formation = initialFormationStrategy.setUpPieces(TeamColor.HAN); + + assertThat(formation.size()).isEqualTo(16); + assertThat(formation.get(Position.of(1, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(7, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(6, 0)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(4, 1)).getPieceType()).isEqualTo(PieceType.KING); + } } - @Test - public void 초나라_바깥상차림일_때_마와_상의_좌표가_올바르다() { - Map formation = initialFormationStrategy.setUpPieces(TeamColor.CHO); - - assertThat(formation.size()).isEqualTo(16); - - // 상좌표 검증 - 초상1(1,9), 초상2(7,9) - assertThat(formation.get(Position.of(1, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(7, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - - // 마좌표 검증 - 초마1(2,9), 초마2(6,9) - assertThat(formation.get(Position.of(2, 9)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(6, 9)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); + @Nested + class 초나라 { + @Test + public void 바깥상차림일_때_마와_상의_좌표가_올바르다() { + Map formation = initialFormationStrategy.setUpPieces(TeamColor.CHO); + + assertThat(formation.size()).isEqualTo(16); + assertThat(formation.get(Position.of(1, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(7, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(2, 9)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(6, 9)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); + } } } diff --git a/src/test/java/strategy/formation/RightFormationStrategyTest.java b/src/test/java/strategy/formation/RightFormationStrategyTest.java index 5242949504..b4b9c28940 100644 --- a/src/test/java/strategy/formation/RightFormationStrategyTest.java +++ b/src/test/java/strategy/formation/RightFormationStrategyTest.java @@ -6,6 +6,7 @@ import domain.TeamColor; import java.util.Map; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -19,27 +20,33 @@ public void setUp() { initialFormationStrategy = new RightFormationStrategy(); } - @Test - public void 한나라_우상차림일_때_마와_상의_좌표가_올바르다() { - Map formation = initialFormationStrategy.setUpPieces(TeamColor.HAN); - - assertThat(formation.size()).isEqualTo(16); - assertThat(formation.get(Position.of(1, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(6, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(7, 0)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(4, 1)).getPieceType()).isEqualTo(PieceType.KING); + @Nested + class 한나라 { + @Test + public void 우상차림일_때_마와_상의_좌표가_올바르다() { + Map formation = initialFormationStrategy.setUpPieces(TeamColor.HAN); + + assertThat(formation.size()).isEqualTo(16); + assertThat(formation.get(Position.of(1, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(6, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(7, 0)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(4, 1)).getPieceType()).isEqualTo(PieceType.KING); + } } - @Test - public void 초나라_우상차림일_때_마와_상의_좌표가_올바르다() { - Map formation = initialFormationStrategy.setUpPieces(TeamColor.CHO); - - assertThat(formation.size()).isEqualTo(16); - assertThat(formation.get(Position.of(1, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(2, 9)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(6, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(7, 9)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); + @Nested + class 초나라 { + @Test + public void 우상차림일_때_마와_상의_좌표가_올바르다() { + Map formation = initialFormationStrategy.setUpPieces(TeamColor.CHO); + + assertThat(formation.size()).isEqualTo(16); + assertThat(formation.get(Position.of(1, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(2, 9)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(6, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(7, 9)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); + } } } diff --git a/src/test/java/strategy/move/CannonMoveStrategyTest.java b/src/test/java/strategy/move/CannonMoveStrategyTest.java index 510e893df8..7e8693c091 100644 --- a/src/test/java/strategy/move/CannonMoveStrategyTest.java +++ b/src/test/java/strategy/move/CannonMoveStrategyTest.java @@ -7,39 +7,46 @@ import domain.PieceType; import domain.TeamColor; import java.util.List; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; + import static org.assertj.core.api.Assertions.assertThat; public class CannonMoveStrategyTest { - @Test - public void 포는_초나라에서_동서남북_4방향을_가진다() { - MoveStrategy strategy = new RookMoveStrategy(); - List paths = strategy.getPaths(TeamColor.CHO); - - assertThat(paths).hasSize(4); - assertThat(paths).containsExactlyInAnyOrder( - new MovePath(List.of(Direction.NORTH)), - new MovePath(List.of(Direction.SOUTH)), - new MovePath(List.of(Direction.EAST)), - new MovePath(List.of(Direction.WEST)) - ); - } + @Nested + class 이동경로 { + @Test + public void 포는_초나라에서_동서남북_4방향을_가진다() { + MoveStrategy strategy = new RookMoveStrategy(); + List paths = strategy.getPaths(TeamColor.CHO); + + assertThat(paths).hasSize(4); + assertThat(paths).containsExactlyInAnyOrder( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)) + ); + } - @Test - public void 포는_한나라에서_동서남북_4방향을_가진다() { - MoveStrategy strategy = new RookMoveStrategy(); - List paths = strategy.getPaths(TeamColor.HAN); - - assertThat(paths).hasSize(4); - assertThat(paths).containsExactlyInAnyOrder( - new MovePath(List.of(Direction.NORTH)), - new MovePath(List.of(Direction.SOUTH)), - new MovePath(List.of(Direction.EAST)), - new MovePath(List.of(Direction.WEST)) - ); + @Test + public void 포는_한나라에서_동서남북_4방향을_가진다() { + MoveStrategy strategy = new RookMoveStrategy(); + List paths = strategy.getPaths(TeamColor.HAN); + + assertThat(paths).hasSize(4); + assertThat(paths).containsExactlyInAnyOrder( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)) + ); + } } + @Nested + class 차단검사 { @Test public void 포는_다리가_되는_기물이_하나도_없으면_지나갈수_없다(){ MoveStrategy moveStrategy = new CannonMoveStrategy(); @@ -48,7 +55,6 @@ public class CannonMoveStrategyTest { BlockingPieces blockingPieces = new BlockingPieces(blocking); boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isFalse(); } @@ -60,7 +66,6 @@ public class CannonMoveStrategyTest { BlockingPieces blockingPieces = new BlockingPieces(blocking); boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isFalse(); } @@ -75,7 +80,6 @@ public class CannonMoveStrategyTest { BlockingPieces blockingPieces = new BlockingPieces(blocking); boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isFalse(); } @@ -90,22 +94,18 @@ public class CannonMoveStrategyTest { BlockingPieces blockingPieces = new BlockingPieces(blocking); boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isFalse(); } - @Test public void 포는_일반_다리를_넘어_빈칸으로_정상적으로_이동가능하다(){ MoveStrategy moveStrategy = new CannonMoveStrategy(); Piece bridgePawn = Piece.of(TeamColor.CHO, PieceType.PAWN); - List blocking = List.of(bridgePawn); BlockingPieces blockingPieces = new BlockingPieces(blocking); boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isTrue(); } @@ -120,7 +120,7 @@ public class CannonMoveStrategyTest { BlockingPieces blockingPieces = new BlockingPieces(blocking); boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isTrue(); } } +} diff --git a/src/test/java/strategy/move/ElephantMoveStrategyTest.java b/src/test/java/strategy/move/ElephantMoveStrategyTest.java index 15e1937998..39b82458a0 100644 --- a/src/test/java/strategy/move/ElephantMoveStrategyTest.java +++ b/src/test/java/strategy/move/ElephantMoveStrategyTest.java @@ -9,76 +9,84 @@ import domain.Route; import domain.TeamColor; import java.util.List; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; + import static org.assertj.core.api.Assertions.assertThat; public class ElephantMoveStrategyTest { - @Test - public void 초나라_상은_직진1칸_대각선2칸으로_이루어진_8개의_경로를_가진다() { - MoveStrategy strategy = new ElephantMoveStrategy(); - List paths = strategy.getPaths(TeamColor.CHO); - - assertThat(paths).hasSize(8); - assertThat(paths).contains( - new MovePath(List.of(Direction.NORTH, Direction.NORTH_EAST, Direction.NORTH_EAST)), - new MovePath(List.of(Direction.NORTH, Direction.NORTH_WEST, Direction.NORTH_WEST)), - new MovePath(List.of(Direction.EAST, Direction.NORTH_EAST, Direction.NORTH_EAST)) - ); - } - - @Test - public void 한나라_상은_직진1칸_대각선2칸으로_이루어진_8개의_경로를_가진다() { - MoveStrategy strategy = new ElephantMoveStrategy(); - List paths = strategy.getPaths(TeamColor.HAN); - - assertThat(paths).hasSize(8); - assertThat(paths).contains( - new MovePath(List.of(Direction.NORTH, Direction.NORTH_EAST, Direction.NORTH_EAST)), - new MovePath(List.of(Direction.NORTH, Direction.NORTH_WEST, Direction.NORTH_WEST)), - new MovePath(List.of(Direction.EAST, Direction.NORTH_EAST, Direction.NORTH_EAST)) - ); + @Nested + class 이동경로 { + @Test + public void 초나라_상은_직진1칸_대각선2칸으로_이루어진_8개의_경로를_가진다() { + MoveStrategy strategy = new ElephantMoveStrategy(); + List paths = strategy.getPaths(TeamColor.CHO); + + assertThat(paths).hasSize(8); + assertThat(paths).contains( + new MovePath(List.of(Direction.NORTH, Direction.NORTH_EAST, Direction.NORTH_EAST)), + new MovePath(List.of(Direction.NORTH, Direction.NORTH_WEST, Direction.NORTH_WEST)), + new MovePath(List.of(Direction.EAST, Direction.NORTH_EAST, Direction.NORTH_EAST)) + ); + } + + @Test + public void 한나라_상은_직진1칸_대각선2칸으로_이루어진_8개의_경로를_가진다() { + MoveStrategy strategy = new ElephantMoveStrategy(); + List paths = strategy.getPaths(TeamColor.HAN); + + assertThat(paths).hasSize(8); + assertThat(paths).contains( + new MovePath(List.of(Direction.NORTH, Direction.NORTH_EAST, Direction.NORTH_EAST)), + new MovePath(List.of(Direction.NORTH, Direction.NORTH_WEST, Direction.NORTH_WEST)), + new MovePath(List.of(Direction.EAST, Direction.NORTH_EAST, Direction.NORTH_EAST)) + ); + } } - @Test - public void 상은_장애물이_없으면_지나갈수_있다(){ - MoveStrategy moveStrategy = new PawnMoveStrategy(); + @Nested + class 차단검사 { + @Test + public void 상은_장애물이_없으면_지나갈수_있다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blocking = List.of(); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + List blocking = List.of(); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isTrue(); - } + assertThat(canJumpTo).isTrue(); + } - @Test - public void 상은_장애물이_하나라도_있으면_지나갈수_없다(){ - MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + @Test + public void 상은_장애물이_하나라도_있으면_지나갈수_없다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); + List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isFalse(); + assertThat(canJumpTo).isFalse(); + } } - @Test - public void 상이_정상적으로_진행경로_좌표를_안다() { - Position curPos = Position.of(4, 4); - MoveStrategy moveStrategy = new ElephantMoveStrategy(); - - List routes = moveStrategy.makeRoutes(curPos, TeamColor.CHO); - assertThat(routes).containsExactlyInAnyOrder( - new Route(curPos, Position.of(1, 2), List.of(Position.of(3, 4), Position.of(2, 3))), - new Route(curPos, Position.of(1, 6), List.of(Position.of(3, 4), Position.of(2, 5))), - - new Route(curPos, Position.of(7, 2), List.of(Position.of(5, 4), Position.of(6, 3))), - new Route(curPos, Position.of(7, 6), List.of(Position.of(5, 4), Position.of(6, 5))), - - new Route(curPos, Position.of(2, 1), List.of(Position.of(4, 3), Position.of(3, 2))), - new Route(curPos, Position.of(6, 1), List.of(Position.of(4, 3), Position.of(5, 2))), - - new Route(curPos, Position.of(2, 7), List.of(Position.of(4, 5), Position.of(3, 6))), - new Route(curPos, Position.of(6, 7), List.of(Position.of(4, 5), Position.of(5, 6))) - ); + @Nested + class 좌표생성 { + @Test + public void 상이_정상적으로_진행경로_좌표를_안다() { + Position curPos = Position.of(4, 4); + MoveStrategy moveStrategy = new ElephantMoveStrategy(); + + List routes = moveStrategy.makeRoutes(curPos, TeamColor.CHO); + assertThat(routes).containsExactlyInAnyOrder( + new Route(curPos, Position.of(1, 2), List.of(Position.of(3, 4), Position.of(2, 3))), + new Route(curPos, Position.of(1, 6), List.of(Position.of(3, 4), Position.of(2, 5))), + new Route(curPos, Position.of(7, 2), List.of(Position.of(5, 4), Position.of(6, 3))), + new Route(curPos, Position.of(7, 6), List.of(Position.of(5, 4), Position.of(6, 5))), + new Route(curPos, Position.of(2, 1), List.of(Position.of(4, 3), Position.of(3, 2))), + new Route(curPos, Position.of(6, 1), List.of(Position.of(4, 3), Position.of(5, 2))), + new Route(curPos, Position.of(2, 7), List.of(Position.of(4, 5), Position.of(3, 6))), + new Route(curPos, Position.of(6, 7), List.of(Position.of(4, 5), Position.of(5, 6))) + ); + } } -} \ No newline at end of file +} diff --git a/src/test/java/strategy/move/GuardMoveStrategyTest.java b/src/test/java/strategy/move/GuardMoveStrategyTest.java index 05e75d7c89..5304ccb176 100644 --- a/src/test/java/strategy/move/GuardMoveStrategyTest.java +++ b/src/test/java/strategy/move/GuardMoveStrategyTest.java @@ -9,87 +9,95 @@ import domain.Route; import domain.TeamColor; import java.util.List; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; + import static org.assertj.core.api.Assertions.assertThat; public class GuardMoveStrategyTest { - @Test - public void 초나라_사는_8방향으로_이동_가능하다() { - MoveStrategy strategy = new KingMoveStrategy(); - List paths = strategy.getPaths(TeamColor.CHO); - - assertThat(paths).hasSize(8); - assertThat(paths).containsExactlyInAnyOrder( - new MovePath(List.of(Direction.NORTH)), - new MovePath(List.of(Direction.SOUTH)), - new MovePath(List.of(Direction.EAST)), - new MovePath(List.of(Direction.WEST)), - new MovePath(List.of(Direction.NORTH_EAST)), - new MovePath(List.of(Direction.NORTH_WEST)), - new MovePath(List.of(Direction.SOUTH_EAST)), - new MovePath(List.of(Direction.SOUTH_WEST)) - ); - } - - @Test - public void 한나라_사는_8방향으로_이동_가능하다() { - MoveStrategy strategy = new KingMoveStrategy(); - List paths = strategy.getPaths(TeamColor.HAN); - - assertThat(paths).hasSize(8); - assertThat(paths).containsExactlyInAnyOrder( - new MovePath(List.of(Direction.NORTH)), - new MovePath(List.of(Direction.SOUTH)), - new MovePath(List.of(Direction.EAST)), - new MovePath(List.of(Direction.WEST)), - new MovePath(List.of(Direction.NORTH_EAST)), - new MovePath(List.of(Direction.NORTH_WEST)), - new MovePath(List.of(Direction.SOUTH_EAST)), - new MovePath(List.of(Direction.SOUTH_WEST)) - ); + @Nested + class 이동경로 { + @Test + public void 초나라_사는_8방향으로_이동_가능하다() { + MoveStrategy strategy = new KingMoveStrategy(); + List paths = strategy.getPaths(TeamColor.CHO); + + assertThat(paths).hasSize(8); + assertThat(paths).containsExactlyInAnyOrder( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)), + new MovePath(List.of(Direction.NORTH_EAST)), + new MovePath(List.of(Direction.NORTH_WEST)), + new MovePath(List.of(Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.SOUTH_WEST)) + ); + } + + @Test + public void 한나라_사는_8방향으로_이동_가능하다() { + MoveStrategy strategy = new KingMoveStrategy(); + List paths = strategy.getPaths(TeamColor.HAN); + + assertThat(paths).hasSize(8); + assertThat(paths).containsExactlyInAnyOrder( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)), + new MovePath(List.of(Direction.NORTH_EAST)), + new MovePath(List.of(Direction.NORTH_WEST)), + new MovePath(List.of(Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.SOUTH_WEST)) + ); + } } - @Test - public void 사는_장애물이_없으면_지나갈수_있다(){ - MoveStrategy moveStrategy = new PawnMoveStrategy(); + @Nested + class 차단검사 { + @Test + public void 사는_장애물이_없으면_지나갈수_있다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blocking = List.of(); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + List blocking = List.of(); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isTrue(); - } + assertThat(canJumpTo).isTrue(); + } - @Test - public void 사는_장애물이_하나라도_있으면_지나갈수_없다(){ - MoveStrategy moveStrategy = new PawnMoveStrategy(); + @Test + public void 사는_장애물이_하나라도_있으면_지나갈수_없다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isFalse(); + assertThat(canJumpTo).isFalse(); + } } - @Test - public void 왕이_정상적으로_진행경로_좌표를_안다() { - Position curPos = Position.of(1, 4); - MoveStrategy moveStrategy = new GuardMoveStrategy(); - - List routes = moveStrategy.makeRoutes(curPos, TeamColor.CHO); - assertThat(routes).containsExactlyInAnyOrder( - - new Route(curPos, Position.of(0, 4), List.of()), - new Route(curPos, Position.of(2, 4), List.of()), - new Route(curPos, Position.of(1, 3), List.of()), - new Route(curPos, Position.of(1, 5), List.of()), - - new Route(curPos, Position.of(0, 3), List.of()), - new Route(curPos, Position.of(0, 5), List.of()), - new Route(curPos, Position.of(2, 3), List.of()), - new Route(curPos, Position.of(2, 5), List.of()) - ); + @Nested + class 좌표생성 { + @Test + public void 왕이_정상적으로_진행경로_좌표를_안다() { + Position curPos = Position.of(1, 4); + MoveStrategy moveStrategy = new GuardMoveStrategy(); + + List routes = moveStrategy.makeRoutes(curPos, TeamColor.CHO); + assertThat(routes).containsExactlyInAnyOrder( + new Route(curPos, Position.of(0, 4), List.of()), + new Route(curPos, Position.of(2, 4), List.of()), + new Route(curPos, Position.of(1, 3), List.of()), + new Route(curPos, Position.of(1, 5), List.of()), + new Route(curPos, Position.of(0, 3), List.of()), + new Route(curPos, Position.of(0, 5), List.of()), + new Route(curPos, Position.of(2, 3), List.of()), + new Route(curPos, Position.of(2, 5), List.of()) + ); + } } } - diff --git a/src/test/java/strategy/move/HorseMoveStrategyTest.java b/src/test/java/strategy/move/HorseMoveStrategyTest.java index 5ad599785b..c2fe153370 100644 --- a/src/test/java/strategy/move/HorseMoveStrategyTest.java +++ b/src/test/java/strategy/move/HorseMoveStrategyTest.java @@ -9,89 +9,95 @@ import domain.Route; import domain.TeamColor; import java.util.List; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; + import static org.assertj.core.api.Assertions.assertThat; public class HorseMoveStrategyTest { - @Test - public void 초나라_마는_직진1칸_대각선1칸으로_이루어진_8개의_경로를_가진다() { - MoveStrategy strategy = new HorseMoveStrategy(); - List paths = strategy.getPaths(TeamColor.CHO); - - assertThat(paths).hasSize(8); - assertThat(paths).contains( - new MovePath(List.of(Direction.NORTH, Direction.NORTH_EAST)), - new MovePath(List.of(Direction.NORTH, Direction.NORTH_WEST)), - new MovePath(List.of(Direction.EAST, Direction.SOUTH_EAST)), - new MovePath(List.of(Direction.EAST, Direction. NORTH_EAST)), - new MovePath(List.of(Direction.SOUTH, Direction.SOUTH_WEST)), - new MovePath(List.of(Direction.SOUTH, Direction.SOUTH_EAST)), - new MovePath(List.of(Direction.WEST, Direction.NORTH_WEST)), - new MovePath(List.of(Direction.WEST, Direction.SOUTH_WEST)) - ); - } - - @Test - public void 한나라_마는_직진1칸_대각선1칸으로_이루어진_8개의_경로를_가진다() { - MoveStrategy strategy = new HorseMoveStrategy(); - List paths = strategy.getPaths(TeamColor.HAN); - - assertThat(paths).hasSize(8); - assertThat(paths).contains( - new MovePath(List.of(Direction.NORTH, Direction.NORTH_EAST)), - new MovePath(List.of(Direction.NORTH, Direction.NORTH_WEST)), - new MovePath(List.of(Direction.EAST, Direction.SOUTH_EAST)), - new MovePath(List.of(Direction.EAST, Direction. NORTH_EAST)), - new MovePath(List.of(Direction.SOUTH, Direction.SOUTH_WEST)), - new MovePath(List.of(Direction.SOUTH, Direction.SOUTH_EAST)), - new MovePath(List.of(Direction.WEST, Direction.NORTH_WEST)), - new MovePath(List.of(Direction.WEST, Direction.SOUTH_WEST)) - ); + @Nested + class 이동경로 { + @Test + public void 초나라_마는_직진1칸_대각선1칸으로_이루어진_8개의_경로를_가진다() { + MoveStrategy strategy = new HorseMoveStrategy(); + List paths = strategy.getPaths(TeamColor.CHO); + + assertThat(paths).hasSize(8); + assertThat(paths).contains( + new MovePath(List.of(Direction.NORTH, Direction.NORTH_EAST)), + new MovePath(List.of(Direction.NORTH, Direction.NORTH_WEST)), + new MovePath(List.of(Direction.EAST, Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.EAST, Direction.NORTH_EAST)), + new MovePath(List.of(Direction.SOUTH, Direction.SOUTH_WEST)), + new MovePath(List.of(Direction.SOUTH, Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.WEST, Direction.NORTH_WEST)), + new MovePath(List.of(Direction.WEST, Direction.SOUTH_WEST)) + ); + } + + @Test + public void 한나라_마는_직진1칸_대각선1칸으로_이루어진_8개의_경로를_가진다() { + MoveStrategy strategy = new HorseMoveStrategy(); + List paths = strategy.getPaths(TeamColor.HAN); + + assertThat(paths).hasSize(8); + assertThat(paths).contains( + new MovePath(List.of(Direction.NORTH, Direction.NORTH_EAST)), + new MovePath(List.of(Direction.NORTH, Direction.NORTH_WEST)), + new MovePath(List.of(Direction.EAST, Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.EAST, Direction.NORTH_EAST)), + new MovePath(List.of(Direction.SOUTH, Direction.SOUTH_WEST)), + new MovePath(List.of(Direction.SOUTH, Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.WEST, Direction.NORTH_WEST)), + new MovePath(List.of(Direction.WEST, Direction.SOUTH_WEST)) + ); + } } - @Test - public void 마는_장애물이_없으면_지나갈수_있다(){ - MoveStrategy moveStrategy = new PawnMoveStrategy(); + @Nested + class 차단검사 { + @Test + public void 마는_장애물이_없으면_지나갈수_있다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blocking= List.of(); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + List blocking= List.of(); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isTrue(); - } + assertThat(canJumpTo).isTrue(); + } - @Test - public void 마는_장애물이_하나라도_있으면_지나갈수_없다(){ - MoveStrategy moveStrategy = new PawnMoveStrategy(); + @Test + public void 마는_장애물이_하나라도_있으면_지나갈수_없다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isFalse(); + assertThat(canJumpTo).isFalse(); + } } - @Test - public void 마가_정상적으로_진행경로_좌표를_안다() { - // 중앙인 (4, 4)에 있다고 가정 (8방향 모두 이동 가능한 위치) - Position curPos = Position.of(4, 4); - MoveStrategy moveStrategy = new HorseMoveStrategy(); - - List routes = moveStrategy.makeRoutes(curPos, TeamColor.CHO); - assertThat(routes).containsExactlyInAnyOrder( - - new Route(curPos, Position.of(2, 3), List.of(Position.of(3, 4))), - new Route(curPos, Position.of(2, 5), List.of(Position.of(3, 4))), - - new Route(curPos, Position.of(6, 3), List.of(Position.of(5, 4))), - new Route(curPos, Position.of(6, 5), List.of(Position.of(5, 4))), - - new Route(curPos, Position.of(3, 2), List.of(Position.of(4, 3))), - new Route(curPos, Position.of(5, 2), List.of(Position.of(4, 3))), - - new Route(curPos, Position.of(3, 6), List.of(Position.of(4, 5))), - new Route(curPos, Position.of(5, 6), List.of(Position.of(4, 5))) - ); + @Nested + class 좌표생성 { + @Test + public void 마가_정상적으로_진행경로_좌표를_안다() { + Position curPos = Position.of(4, 4); + MoveStrategy moveStrategy = new HorseMoveStrategy(); + + List routes = moveStrategy.makeRoutes(curPos, TeamColor.CHO); + assertThat(routes).containsExactlyInAnyOrder( + new Route(curPos, Position.of(2, 3), List.of(Position.of(3, 4))), + new Route(curPos, Position.of(2, 5), List.of(Position.of(3, 4))), + new Route(curPos, Position.of(6, 3), List.of(Position.of(5, 4))), + new Route(curPos, Position.of(6, 5), List.of(Position.of(5, 4))), + new Route(curPos, Position.of(3, 2), List.of(Position.of(4, 3))), + new Route(curPos, Position.of(5, 2), List.of(Position.of(4, 3))), + new Route(curPos, Position.of(3, 6), List.of(Position.of(4, 5))), + new Route(curPos, Position.of(5, 6), List.of(Position.of(4, 5))) + ); + } } -} \ No newline at end of file +} diff --git a/src/test/java/strategy/move/KingMoveStrategyTest.java b/src/test/java/strategy/move/KingMoveStrategyTest.java index 25724c6095..f27f6024b6 100644 --- a/src/test/java/strategy/move/KingMoveStrategyTest.java +++ b/src/test/java/strategy/move/KingMoveStrategyTest.java @@ -9,89 +9,95 @@ import domain.Route; import domain.TeamColor; import java.util.List; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; + import static org.assertj.core.api.Assertions.assertThat; public class KingMoveStrategyTest { - @Test - public void 초나라_왕은_8방향으로_이동_가능하다() { - MoveStrategy strategy = new KingMoveStrategy(); - List paths = strategy.getPaths(TeamColor.CHO); - - assertThat(paths).hasSize(8); - assertThat(paths).containsExactlyInAnyOrder( - new MovePath(List.of(Direction.NORTH)), - new MovePath(List.of(Direction.SOUTH)), - new MovePath(List.of(Direction.EAST)), - new MovePath(List.of(Direction.WEST)), - new MovePath(List.of(Direction.NORTH_EAST)), - new MovePath(List.of(Direction.NORTH_WEST)), - new MovePath(List.of(Direction.SOUTH_EAST)), - new MovePath(List.of(Direction.SOUTH_WEST)) - ); - } - - @Test - public void 한나라_왕은_8방향으로_이동_가능하다() { - MoveStrategy strategy = new KingMoveStrategy(); - List paths = strategy.getPaths(TeamColor.HAN); - - assertThat(paths).hasSize(8); - assertThat(paths).containsExactlyInAnyOrder( - new MovePath(List.of(Direction.NORTH)), - new MovePath(List.of(Direction.SOUTH)), - new MovePath(List.of(Direction.EAST)), - new MovePath(List.of(Direction.WEST)), - new MovePath(List.of(Direction.NORTH_EAST)), - new MovePath(List.of(Direction.NORTH_WEST)), - new MovePath(List.of(Direction.SOUTH_EAST)), - new MovePath(List.of(Direction.SOUTH_WEST)) - ); + @Nested + class 이동경로 { + @Test + public void 초나라_왕은_8방향으로_이동_가능하다() { + MoveStrategy strategy = new KingMoveStrategy(); + List paths = strategy.getPaths(TeamColor.CHO); + + assertThat(paths).hasSize(8); + assertThat(paths).containsExactlyInAnyOrder( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)), + new MovePath(List.of(Direction.NORTH_EAST)), + new MovePath(List.of(Direction.NORTH_WEST)), + new MovePath(List.of(Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.SOUTH_WEST)) + ); + } + + @Test + public void 한나라_왕은_8방향으로_이동_가능하다() { + MoveStrategy strategy = new KingMoveStrategy(); + List paths = strategy.getPaths(TeamColor.HAN); + + assertThat(paths).hasSize(8); + assertThat(paths).containsExactlyInAnyOrder( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)), + new MovePath(List.of(Direction.NORTH_EAST)), + new MovePath(List.of(Direction.NORTH_WEST)), + new MovePath(List.of(Direction.SOUTH_EAST)), + new MovePath(List.of(Direction.SOUTH_WEST)) + ); + } } - @Test - public void 왕은_장애물이_없으면_지나갈수_있다(){ - MoveStrategy moveStrategy = new PawnMoveStrategy(); + @Nested + class 차단검사 { + @Test + public void 왕은_장애물이_없으면_지나갈수_있다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blocking = List.of(); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + List blocking = List.of(); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isTrue(); - } + assertThat(canJumpTo).isTrue(); + } - @Test - public void 왕은_장애물이_하나라도_있으면_지나갈수_없다(){ - MoveStrategy moveStrategy = new PawnMoveStrategy(); + @Test + public void 왕은_장애물이_하나라도_있으면_지나갈수_없다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isFalse(); + assertThat(canJumpTo).isFalse(); + } } - @Test - public void 왕이_정상적으로_진행경로_좌표를_안다() { - - Position curPos = Position.of(1, 4); - MoveStrategy moveStrategy = new KingMoveStrategy(); - - List routes = moveStrategy.makeRoutes(curPos, TeamColor.CHO); - assertThat(routes).containsExactlyInAnyOrder( - - new Route(curPos, Position.of(0, 4), List.of()), - new Route(curPos, Position.of(2, 4), List.of()), - new Route(curPos, Position.of(1, 3), List.of()), - new Route(curPos, Position.of(1, 5), List.of()), - - new Route(curPos, Position.of(0, 3), List.of()), - new Route(curPos, Position.of(0, 5), List.of()), - new Route(curPos, Position.of(2, 3), List.of()), - new Route(curPos, Position.of(2, 5), List.of()) - ); + @Nested + class 좌표생성 { + @Test + public void 왕이_정상적으로_진행경로_좌표를_안다() { + Position curPos = Position.of(1, 4); + MoveStrategy moveStrategy = new KingMoveStrategy(); + + List routes = moveStrategy.makeRoutes(curPos, TeamColor.CHO); + assertThat(routes).containsExactlyInAnyOrder( + new Route(curPos, Position.of(0, 4), List.of()), + new Route(curPos, Position.of(2, 4), List.of()), + new Route(curPos, Position.of(1, 3), List.of()), + new Route(curPos, Position.of(1, 5), List.of()), + new Route(curPos, Position.of(0, 3), List.of()), + new Route(curPos, Position.of(0, 5), List.of()), + new Route(curPos, Position.of(2, 3), List.of()), + new Route(curPos, Position.of(2, 5), List.of()) + ); + } } - } - diff --git a/src/test/java/strategy/move/PawnMoveStrategyTest.java b/src/test/java/strategy/move/PawnMoveStrategyTest.java index 49e09299a2..da476ed908 100644 --- a/src/test/java/strategy/move/PawnMoveStrategyTest.java +++ b/src/test/java/strategy/move/PawnMoveStrategyTest.java @@ -10,7 +10,9 @@ import domain.TeamColor; import java.util.List; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; + import static org.assertj.core.api.Assertions.assertThat; public class PawnMoveStrategyTest { @@ -22,75 +24,80 @@ public void setUp() { piece = Piece.of(TeamColor.CHO, PieceType.PAWN); } - - @Test - public void 초나라_졸은_북동서로_이동_가능하다() { - MoveStrategy moveStrategy = new PawnMoveStrategy(); - List movePathList = moveStrategy.getPaths(TeamColor.CHO); - assertThat(movePathList).contains(new MovePath(List.of(Direction.NORTH))); - assertThat(movePathList).contains(new MovePath(List.of(Direction.WEST))); - assertThat(movePathList).contains(new MovePath(List.of(Direction.EAST))); - assertThat(movePathList).doesNotContain(new MovePath(List.of(Direction.SOUTH))); + @Nested + class 이동경로 { + @Test + public void 초나라_졸은_북동서로_이동_가능하다() { + MoveStrategy moveStrategy = new PawnMoveStrategy(); + List movePathList = moveStrategy.getPaths(TeamColor.CHO); + assertThat(movePathList).contains(new MovePath(List.of(Direction.NORTH))); + assertThat(movePathList).contains(new MovePath(List.of(Direction.WEST))); + assertThat(movePathList).contains(new MovePath(List.of(Direction.EAST))); + assertThat(movePathList).doesNotContain(new MovePath(List.of(Direction.SOUTH))); + } + + @Test + public void 한나라_졸은_남동서로_이동_가능하다() { + MoveStrategy moveStrategy = new PawnMoveStrategy(); + List movePaths = moveStrategy.getPaths(TeamColor.HAN); + assertThat(movePaths).contains(new MovePath(List.of(Direction.SOUTH))); + assertThat(movePaths).contains(new MovePath(List.of(Direction.WEST))); + assertThat(movePaths).contains(new MovePath(List.of(Direction.EAST))); + assertThat(movePaths).doesNotContain(new MovePath(List.of(Direction.NORTH))); + } } - @Test - public void 한나라_졸은_남동서로_이동_가능하다() { - MoveStrategy moveStrategy = new PawnMoveStrategy(); - List movePaths = moveStrategy.getPaths(TeamColor.HAN); - assertThat(movePaths).contains(new MovePath(List.of(Direction.SOUTH))); - assertThat(movePaths).contains(new MovePath(List.of(Direction.WEST))); - assertThat(movePaths).contains(new MovePath(List.of(Direction.EAST))); - assertThat(movePaths).doesNotContain(new MovePath(List.of(Direction.NORTH))); + @Nested + class 좌표생성 { + @Test + public void 초나라_졸이_정상적으로_진행경로_좌표를_안다(){ + Position curPos = Position.of(2,3); + MoveStrategy moveStrategy = new PawnMoveStrategy(); + + List routes = moveStrategy.makeRoutes(curPos, TeamColor.CHO); + assertThat(routes).containsExactlyInAnyOrder( + new Route(curPos, Position.of(1, 3), List.of()), + new Route(curPos, Position.of(2, 4), List.of()), + new Route(curPos, Position.of(2, 2), List.of()) + ); + } + + @Test + public void 한나라_졸은_현재위치와_이동방향을_기반으로_이동가능한_좌표들_구한다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); + Position curPos = Position.of(3,4); + + List possibleRoutes = moveStrategy.makeRoutes(curPos, TeamColor.HAN); + assertThat(possibleRoutes).containsExactlyInAnyOrder( + new Route(curPos,Position.of(4,4),List.of()), + new Route(curPos,Position.of(3,5),List.of()), + new Route(curPos,Position.of(3,3),List.of()) + ); + } } + @Nested + class 차단검사 { + @Test + public void 졸은_장애물이_없으면_지나갈수_있다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); - @Test - public void 초나라_졸이_정상적으로_진행경로_좌표를_안다(){ - Position curPos = Position.of(2,3); - MoveStrategy moveStrategy = new PawnMoveStrategy(); - - List routes = moveStrategy.makeRoutes(curPos, TeamColor.CHO); - assertThat(routes).containsExactlyInAnyOrder( - new Route(curPos, Position.of(1, 3), List.of()), - new Route(curPos, Position.of(2, 4), List.of()), - new Route(curPos, Position.of(2, 2), List.of()) - ); - } + List blocking = List.of(); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - @Test - public void 한나라_졸은_현재위치와_이동방향을_기반으로_이동가능한_좌표들_구한다(){ - MoveStrategy moveStrategy = new PawnMoveStrategy(); - Position curPos = Position.of(3,4); - - List possibleRoutes = moveStrategy.makeRoutes(curPos, TeamColor.HAN); - assertThat(possibleRoutes).containsExactlyInAnyOrder( - new Route(curPos,Position.of(4,4),List.of()), - new Route(curPos,Position.of(3,5),List.of()), - new Route(curPos,Position.of(3,3),List.of()) - ); - } + assertThat(canJumpTo).isTrue(); + } - @Test - public void 졸은_장애물이_없으면_지나갈수_있다(){ - MoveStrategy moveStrategy = new PawnMoveStrategy(); + @Test + public void 졸은_장애물이_하나라도_있으면_지나갈수_없다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blocking = List.of(); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + List blocking = List.of(Piece.of(TeamColor.CHO,PieceType.CANNON)); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isTrue(); + assertThat(canJumpTo).isFalse(); + } } - - @Test - public void 졸은_장애물이_하나라도_있으면_지나갈수_없다(){ - MoveStrategy moveStrategy = new PawnMoveStrategy(); - - List blocking = List.of(Piece.of(TeamColor.CHO,PieceType.CANNON)); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - - assertThat(canJumpTo).isFalse(); - } - - } diff --git a/src/test/java/strategy/move/RookMoveStrategyTest.java b/src/test/java/strategy/move/RookMoveStrategyTest.java index 97e24d047d..a01d49c4f8 100644 --- a/src/test/java/strategy/move/RookMoveStrategyTest.java +++ b/src/test/java/strategy/move/RookMoveStrategyTest.java @@ -7,58 +7,66 @@ import domain.PieceType; import domain.TeamColor; import java.util.List; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; + import static org.assertj.core.api.Assertions.assertThat; public class RookMoveStrategyTest { - @Test - public void 차는_초나라에서_동서남북_4방향을_가진다() { - MoveStrategy strategy = new RookMoveStrategy(); - List paths = strategy.getPaths(TeamColor.CHO); + @Nested + class 이동경로 { + @Test + public void 차는_초나라에서_동서남북_4방향을_가진다() { + MoveStrategy strategy = new RookMoveStrategy(); + List paths = strategy.getPaths(TeamColor.CHO); - assertThat(paths).hasSize(4); - assertThat(paths).containsExactlyInAnyOrder( - new MovePath(List.of(Direction.NORTH)), - new MovePath(List.of(Direction.SOUTH)), - new MovePath(List.of(Direction.EAST)), - new MovePath(List.of(Direction.WEST)) - ); - } + assertThat(paths).hasSize(4); + assertThat(paths).containsExactlyInAnyOrder( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)) + ); + } - @Test - public void 차는_한나라에서_동서남북_4방향을_가진다() { - MoveStrategy strategy = new RookMoveStrategy(); - List paths = strategy.getPaths(TeamColor.HAN); + @Test + public void 차는_한나라에서_동서남북_4방향을_가진다() { + MoveStrategy strategy = new RookMoveStrategy(); + List paths = strategy.getPaths(TeamColor.HAN); - assertThat(paths).hasSize(4); - assertThat(paths).containsExactlyInAnyOrder( - new MovePath(List.of(Direction.NORTH)), - new MovePath(List.of(Direction.SOUTH)), - new MovePath(List.of(Direction.EAST)), - new MovePath(List.of(Direction.WEST)) - ); + assertThat(paths).hasSize(4); + assertThat(paths).containsExactlyInAnyOrder( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)) + ); + } } - @Test - public void 차는_장애물이_없으면_지나갈수_있다(){ - MoveStrategy moveStrategy = new PawnMoveStrategy(); + @Nested + class 차단검사 { + @Test + public void 차는_장애물이_없으면_지나갈수_있다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blocking = List.of(); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + List blocking = List.of(); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isTrue(); - } + assertThat(canJumpTo).isTrue(); + } - @Test - public void 차는_장애물이_하나라도_있으면_지나갈수_없다(){ - MoveStrategy moveStrategy = new PawnMoveStrategy(); + @Test + public void 차는_장애물이_하나라도_있으면_지나갈수_없다(){ + MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); + BlockingPieces blockingPieces = new BlockingPieces(blocking); + boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isFalse(); + assertThat(canJumpTo).isFalse(); + } } } From b534fa8b6c98e6ea699e45c3e7804350d7eac189 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 20:59:08 +0900 Subject: [PATCH 53/82] feat: add board route inspection --- src/main/java/domain/Board.java | 25 +++++++++++ src/test/java/domain/BoardTest.java | 65 +++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 src/main/java/domain/Board.java create mode 100644 src/test/java/domain/BoardTest.java diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java new file mode 100644 index 0000000000..255ad00cff --- /dev/null +++ b/src/main/java/domain/Board.java @@ -0,0 +1,25 @@ +package domain; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class Board { + + private final Map pieces; + + public Board(Map pieces) { + this.pieces = Map.copyOf(pieces); + } + + public List getBlockingPieces(Route route) { + return route.intermeidateNodes().stream() + .map(pieces::get) + .filter(piece -> piece != null) + .toList(); + } + + public Optional getDestinationPiece(Route route) { + return Optional.ofNullable(pieces.get(route.endPos())); + } +} diff --git a/src/test/java/domain/BoardTest.java b/src/test/java/domain/BoardTest.java new file mode 100644 index 0000000000..6efabb4059 --- /dev/null +++ b/src/test/java/domain/BoardTest.java @@ -0,0 +1,65 @@ +package domain; + +import java.util.Map; +import java.util.Optional; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class BoardTest { + + private Board board; + private Piece choPawn; + private Piece hanHorse; + private Piece choCannon; + + @BeforeEach + void setUp() { + choPawn = Piece.of(TeamColor.CHO, PieceType.PAWN); + hanHorse = Piece.of(TeamColor.HAN, PieceType.HORSE); + choCannon = Piece.of(TeamColor.CHO, PieceType.CANNON); + board = new Board(Map.of( + Position.of(3, 4), choPawn, + Position.of(2, 4), hanHorse, + Position.of(1, 4), choCannon + )); + } + + @Nested + class 사실조회 { + @Test + void 경로_중간에_놓인_기물들을_순서대로_반환한다() { + Route route = new Route( + Position.of(4, 4), + Position.of(1, 4), + java.util.List.of(Position.of(3, 4), Position.of(2, 4)) + ); + + assertThat(board.getBlockingPieces(route)).containsExactly(choPawn, hanHorse); + } + + @Test + void 도착지_기물이_있으면_반환한다() { + Route route = new Route( + Position.of(4, 4), + Position.of(1, 4), + java.util.List.of(Position.of(3, 4), Position.of(2, 4)) + ); + + assertThat(board.getDestinationPiece(route)).contains(choCannon); + } + + @Test + void 도착지_기물이_없으면_빈_Optional을_반환한다() { + Route route = new Route( + Position.of(4, 4), + Position.of(0, 4), + java.util.List.of(Position.of(3, 4), Position.of(2, 4), Position.of(1, 4)) + ); + + assertThat(board.getDestinationPiece(route)).isEqualTo(Optional.empty()); + } + } +} From 351b8787ca1a7ea92c56306ef45e1e8d30255024 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 21:04:21 +0900 Subject: [PATCH 54/82] refactor: delegate move validation to piece strategies --- src/main/java/domain/Board.java | 34 ++++++++- src/main/java/domain/Piece.java | 41 +++++++++-- .../strategy/move/CannonMoveStrategy.java | 29 +++++--- .../strategy/move/ElephantMoveStrategy.java | 22 +----- .../java/strategy/move/GuardMoveStrategy.java | 18 ----- .../java/strategy/move/HorseMoveStrategy.java | 19 +---- .../java/strategy/move/KingMoveStrategy.java | 18 ----- src/main/java/strategy/move/MoveStrategy.java | 13 +++- .../java/strategy/move/PawnMoveStrategy.java | 20 ------ .../java/strategy/move/RookMoveStrategy.java | 16 ----- src/test/java/domain/BoardTest.java | 25 +++++++ src/test/java/domain/PieceTest.java | 39 ++++++++++ .../strategy/move/CannonMoveStrategyTest.java | 72 +++++++++++-------- .../move/ElephantMoveStrategyTest.java | 22 +++--- .../strategy/move/GuardMoveStrategyTest.java | 21 +++--- .../strategy/move/HorseMoveStrategyTest.java | 21 +++--- .../strategy/move/KingMoveStrategyTest.java | 21 +++--- .../strategy/move/PawnMoveStrategyTest.java | 21 +++--- .../strategy/move/RookMoveStrategyTest.java | 23 +++--- 19 files changed, 284 insertions(+), 211 deletions(-) create mode 100644 src/test/java/domain/PieceTest.java diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index 255ad00cff..4aea9eb480 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -1,5 +1,6 @@ package domain; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; @@ -9,7 +10,7 @@ public class Board { private final Map pieces; public Board(Map pieces) { - this.pieces = Map.copyOf(pieces); + this.pieces = new HashMap<>(pieces); } public List getBlockingPieces(Route route) { @@ -22,4 +23,35 @@ public List getBlockingPieces(Route route) { public Optional getDestinationPiece(Route route) { return Optional.ofNullable(pieces.get(route.endPos())); } + + public Optional findPositionOf(Piece piece) { + return pieces.entrySet().stream() + .filter(entry -> entry.getValue() == piece) + .map(Map.Entry::getKey) + .findFirst(); + } + + public Optional findPiece(Position position) { + return Optional.ofNullable(pieces.get(position)); + } + + public void move(Piece piece, Position destination) { + Position currentPosition = findPositionOf(piece) + .orElseThrow(() -> new IllegalArgumentException("보드에 없는 기물입니다.")); + + Route route = piece.makeRoutes(currentPosition).stream() + .filter(candidate -> candidate.endPos().equals(destination)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("해당 기물은 목적지로 이동할 수 없습니다.")); + + List blockingPieces = getBlockingPieces(route); + Optional destinationPiece = getDestinationPiece(route); + + if (!piece.canMove(route, blockingPieces, destinationPiece)) { + throw new IllegalArgumentException("현재 판 상태에서는 해당 목적지로 이동할 수 없습니다."); + } + + pieces.remove(currentPosition); + pieces.put(destination, piece); + } } diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/Piece.java index ca14ba8589..c75c9596ca 100644 --- a/src/main/java/domain/Piece.java +++ b/src/main/java/domain/Piece.java @@ -1,12 +1,25 @@ package domain; +import java.util.List; +import java.util.Optional; +import strategy.move.CannonMoveStrategy; +import strategy.move.ElephantMoveStrategy; +import strategy.move.GuardMoveStrategy; +import strategy.move.HorseMoveStrategy; +import strategy.move.KingMoveStrategy; +import strategy.move.MoveStrategy; +import strategy.move.PawnMoveStrategy; +import strategy.move.RookMoveStrategy; + public class Piece { - private TeamColor teamColor; - private PieceType pieceType; + private final TeamColor teamColor; + private final PieceType pieceType; + private final MoveStrategy moveStrategy; - private Piece(TeamColor teamColor, PieceType pieceType) { + private Piece(TeamColor teamColor, PieceType pieceType, MoveStrategy moveStrategy) { this.teamColor = teamColor; this.pieceType = pieceType; + this.moveStrategy = moveStrategy; } public PieceType getPieceType() { @@ -17,7 +30,27 @@ public TeamColor getTeamColor() { return this.teamColor; } + public List makeRoutes(Position from) { + return moveStrategy.makeRoutes(from, teamColor); + } + + public boolean canMove(Route route, List blockingPieces, Optional destinationPiece) { + return moveStrategy.canMove(route, blockingPieces, destinationPiece, teamColor); + } + public static Piece of(TeamColor teamColor, PieceType pieceType) { - return new Piece(teamColor,pieceType); + return new Piece(teamColor, pieceType, createMoveStrategy(pieceType)); + } + + private static MoveStrategy createMoveStrategy(PieceType pieceType) { + return switch (pieceType) { + case CANNON -> new CannonMoveStrategy(); + case ELEPHANT -> new ElephantMoveStrategy(); + case GUARD -> new GuardMoveStrategy(); + case HORSE -> new HorseMoveStrategy(); + case KING -> new KingMoveStrategy(); + case PAWN -> new PawnMoveStrategy(); + case ROOK -> new RookMoveStrategy(); + }; } } diff --git a/src/main/java/strategy/move/CannonMoveStrategy.java b/src/main/java/strategy/move/CannonMoveStrategy.java index 125cc6cfee..3984af625f 100644 --- a/src/main/java/strategy/move/CannonMoveStrategy.java +++ b/src/main/java/strategy/move/CannonMoveStrategy.java @@ -1,10 +1,13 @@ package strategy.move; -import domain.BlockingPieces; import domain.Direction; import domain.MovePath; +import domain.Piece; +import domain.PieceType; +import domain.Route; import domain.TeamColor; import java.util.List; +import java.util.Optional; public class CannonMoveStrategy implements MoveStrategy { @@ -21,21 +24,29 @@ public List getPaths(TeamColor teamColor) { } @Override - public boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam) { - if (blockingPieces.size() == 0) { + public boolean canMove(Route route, List blockingPieces, Optional destinationPiece, TeamColor myTeam) { + if (blockingPieces.isEmpty()) { return false; } - if (blockingPieces.isFirstPieceCannon()) { + if (blockingPieces.size() != 1) { return false; } - if (blockingPieces.size() == 2) { - if (blockingPieces.isLastPieceCannon() || blockingPieces.isLastPieceSameTeam(myTeam)) { - return false; - } + Piece bridgePiece = blockingPieces.getFirst(); + if (bridgePiece.getPieceType() == PieceType.CANNON) { + return false; + } + + if (destinationPiece.isEmpty()) { + return true; + } + + Piece targetPiece = destinationPiece.get(); + if (targetPiece.getPieceType() == PieceType.CANNON) { + return false; } - return true; + return targetPiece.getTeamColor() != myTeam; } } diff --git a/src/main/java/strategy/move/ElephantMoveStrategy.java b/src/main/java/strategy/move/ElephantMoveStrategy.java index 8b16c8734e..1d4e8a5b70 100644 --- a/src/main/java/strategy/move/ElephantMoveStrategy.java +++ b/src/main/java/strategy/move/ElephantMoveStrategy.java @@ -1,15 +1,11 @@ package strategy.move; -import domain.BlockingPieces; import domain.Direction; import domain.MovePath; -import domain.Piece; -import domain.Position; -import domain.Route; import domain.TeamColor; import java.util.List; - public class ElephantMoveStrategy implements MoveStrategy { +public class ElephantMoveStrategy implements MoveStrategy { private static final List PATHS = List.of( new MovePath(List.of(Direction.NORTH, Direction.NORTH_EAST, Direction.NORTH_EAST)), @@ -27,18 +23,4 @@ public List getPaths(TeamColor teamColor) { return PATHS; } - @Override - public boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam) { - if (blockingPieces.size() == 0) { - return true; - } - - if (blockingPieces.size() == 1) { - TeamColor targetTeam = blockingPieces.getFirstBlockingTeamColor(); - return targetTeam != myTeam; - } - - return false; - } - -} \ No newline at end of file +} diff --git a/src/main/java/strategy/move/GuardMoveStrategy.java b/src/main/java/strategy/move/GuardMoveStrategy.java index 6921b0b702..c619d7975a 100644 --- a/src/main/java/strategy/move/GuardMoveStrategy.java +++ b/src/main/java/strategy/move/GuardMoveStrategy.java @@ -1,11 +1,7 @@ package strategy.move; -import domain.BlockingPieces; import domain.Direction; import domain.MovePath; -import domain.Piece; -import domain.Position; -import domain.Route; import domain.TeamColor; import java.util.List; @@ -26,18 +22,4 @@ public class GuardMoveStrategy implements MoveStrategy { public List getPaths(TeamColor teamColor) { return PATHS; } - - @Override - public boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam) { - if (blockingPieces.size() == 0) { - return true; - } - - if (blockingPieces.size() == 1) { - TeamColor targetTeam = blockingPieces.getFirstBlockingTeamColor(); - return targetTeam != myTeam; - } - - return false; - } } diff --git a/src/main/java/strategy/move/HorseMoveStrategy.java b/src/main/java/strategy/move/HorseMoveStrategy.java index b4ffb29665..17652101f1 100644 --- a/src/main/java/strategy/move/HorseMoveStrategy.java +++ b/src/main/java/strategy/move/HorseMoveStrategy.java @@ -1,10 +1,7 @@ package strategy.move; -import domain.BlockingPieces; import domain.Direction; import domain.MovePath; -import domain.Piece; - import domain.TeamColor; import java.util.List; @@ -25,18 +22,4 @@ public class HorseMoveStrategy implements MoveStrategy { public List getPaths(TeamColor teamColor) { return PATHS; } - - @Override - public boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam) { - if (blockingPieces.size() == 0) { - return true; - } - - if (blockingPieces.size() == 1) { - TeamColor targetTeam = blockingPieces.getFirstBlockingTeamColor(); - return targetTeam != myTeam; - } - - return false; - } -} \ No newline at end of file +} diff --git a/src/main/java/strategy/move/KingMoveStrategy.java b/src/main/java/strategy/move/KingMoveStrategy.java index 297eb9b877..d2a357914d 100644 --- a/src/main/java/strategy/move/KingMoveStrategy.java +++ b/src/main/java/strategy/move/KingMoveStrategy.java @@ -1,11 +1,7 @@ package strategy.move; -import domain.BlockingPieces; import domain.Direction; import domain.MovePath; -import domain.Piece; -import domain.Position; -import domain.Route; import domain.TeamColor; import java.util.List; @@ -26,18 +22,4 @@ public class KingMoveStrategy implements MoveStrategy { public List getPaths(TeamColor teamColor) { return PATHS; } - - @Override - public boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam) { - if (blockingPieces.size() == 0) { - return true; - } - - if (blockingPieces.size() == 1) { - TeamColor targetTeam = blockingPieces.getFirstBlockingTeamColor(); - return targetTeam != myTeam; - } - - return false; - } } diff --git a/src/main/java/strategy/move/MoveStrategy.java b/src/main/java/strategy/move/MoveStrategy.java index ab382f725b..202da282fc 100644 --- a/src/main/java/strategy/move/MoveStrategy.java +++ b/src/main/java/strategy/move/MoveStrategy.java @@ -1,13 +1,14 @@ package strategy.move; -import domain.BlockingPieces; import domain.Direction; import domain.MovePath; +import domain.Piece; import domain.Position; +import domain.Route; import domain.TeamColor; import java.util.ArrayList; import java.util.List; -import domain.Route; +import java.util.Optional; public interface MoveStrategy { @@ -36,6 +37,12 @@ default List makeRoutes(Position curPos, TeamColor teamColor) { return validRoutes; } - boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam); + default boolean canMove(Route route, List blockingPieces, Optional destinationPiece, TeamColor myTeam) { + if (!blockingPieces.isEmpty()) { + return false; + } + + return destinationPiece.isEmpty() || destinationPiece.get().getTeamColor() != myTeam; + } } diff --git a/src/main/java/strategy/move/PawnMoveStrategy.java b/src/main/java/strategy/move/PawnMoveStrategy.java index ce9ad1beaf..6fcd856989 100644 --- a/src/main/java/strategy/move/PawnMoveStrategy.java +++ b/src/main/java/strategy/move/PawnMoveStrategy.java @@ -1,13 +1,8 @@ package strategy.move; -import domain.BlockingPieces; import domain.Direction; import domain.MovePath; -import domain.Piece; -import domain.Position; -import domain.Route; import domain.TeamColor; -import java.util.ArrayList; import java.util.List; public class PawnMoveStrategy implements MoveStrategy{ @@ -29,19 +24,4 @@ public List getPaths(TeamColor teamColor) { new MovePath(List.of(Direction.WEST)) ); } - - @Override - public boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam) { - if (blockingPieces.size() == 0) { - return true; - } - - if (blockingPieces.size() == 1) { - TeamColor targetTeam = blockingPieces.getFirstBlockingTeamColor(); - return targetTeam != myTeam; - } - - return false; - } - } diff --git a/src/main/java/strategy/move/RookMoveStrategy.java b/src/main/java/strategy/move/RookMoveStrategy.java index 03db490c7c..331da83ec6 100644 --- a/src/main/java/strategy/move/RookMoveStrategy.java +++ b/src/main/java/strategy/move/RookMoveStrategy.java @@ -1,6 +1,5 @@ package strategy.move; -import domain.BlockingPieces; import domain.Direction; import domain.MovePath; import domain.TeamColor; @@ -20,19 +19,4 @@ public List getPaths(TeamColor teamColor) { return PATHS; } - - @Override - public boolean canJump(BlockingPieces blockingPieces, TeamColor myTeam) { - if (blockingPieces.size() == 0) { - return true; - } - - if (blockingPieces.size() == 1) { - TeamColor targetTeam = blockingPieces.getFirstBlockingTeamColor(); - return targetTeam != myTeam; - } - - return false; - } - } diff --git a/src/test/java/domain/BoardTest.java b/src/test/java/domain/BoardTest.java index 6efabb4059..13e9ee693f 100644 --- a/src/test/java/domain/BoardTest.java +++ b/src/test/java/domain/BoardTest.java @@ -62,4 +62,29 @@ class 사실조회 { assertThat(board.getDestinationPiece(route)).isEqualTo(Optional.empty()); } } + + @Nested + class 위치조회 { + @Test + void 특정_기물의_현재_위치를_찾는다() { + assertThat(board.findPositionOf(hanHorse)).contains(Position.of(2, 4)); + } + } + + @Nested + class 이동 { + @Test + void 기물과_도착지를_받아_실제_이동을_반영한다() { + Piece movingPawn = Piece.of(TeamColor.CHO, PieceType.PAWN); + Board movableBoard = new Board(Map.of( + Position.of(4, 4), movingPawn + )); + + movableBoard.move(movingPawn, Position.of(3, 4)); + + assertThat(movableBoard.findPositionOf(movingPawn)).contains(Position.of(3, 4)); + assertThat(movableBoard.findPiece(Position.of(4, 4))).isEmpty(); + assertThat(movableBoard.findPiece(Position.of(3, 4))).contains(movingPawn); + } + } } diff --git a/src/test/java/domain/PieceTest.java b/src/test/java/domain/PieceTest.java new file mode 100644 index 0000000000..3414f0ac2f --- /dev/null +++ b/src/test/java/domain/PieceTest.java @@ -0,0 +1,39 @@ +package domain; + +import java.util.List; +import java.util.Optional; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class PieceTest { + + @Nested + class 전략위임 { + @Test + void 기물은_자기_전략으로_후보_경로를_생성한다() { + Piece piece = Piece.of(TeamColor.CHO, PieceType.PAWN); + + assertThat(piece.makeRoutes(Position.of(2, 3))).containsExactlyInAnyOrder( + new Route(Position.of(2, 3), Position.of(1, 3), List.of()), + new Route(Position.of(2, 3), Position.of(2, 4), List.of()), + new Route(Position.of(2, 3), Position.of(2, 2), List.of()) + ); + } + + @Test + void 기물은_자기_전략으로_이동_가능_여부를_판단한다() { + Piece piece = Piece.of(TeamColor.CHO, PieceType.PAWN); + Route route = new Route(Position.of(2, 3), Position.of(1, 3), List.of()); + + boolean canMove = piece.canMove( + route, + List.of(), + Optional.of(Piece.of(TeamColor.HAN, PieceType.HORSE)) + ); + + assertThat(canMove).isTrue(); + } + } +} diff --git a/src/test/java/strategy/move/CannonMoveStrategyTest.java b/src/test/java/strategy/move/CannonMoveStrategyTest.java index 7e8693c091..30370905fc 100644 --- a/src/test/java/strategy/move/CannonMoveStrategyTest.java +++ b/src/test/java/strategy/move/CannonMoveStrategyTest.java @@ -1,12 +1,14 @@ package strategy.move; -import domain.BlockingPieces; import domain.Direction; import domain.MovePath; import domain.Piece; import domain.PieceType; +import domain.Position; +import domain.Route; import domain.TeamColor; import java.util.List; +import java.util.Optional; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -50,23 +52,24 @@ class 차단검사 { @Test public void 포는_다리가_되는_기물이_하나도_없으면_지나갈수_없다(){ MoveStrategy moveStrategy = new CannonMoveStrategy(); + Route route = new Route(Position.of(4, 4), Position.of(1, 4), List.of(Position.of(3, 4), Position.of(2, 4))); - List blocking = List.of(); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isFalse(); + boolean canMove = moveStrategy.canMove(route, List.of(), Optional.empty(), TeamColor.CHO); + assertThat(canMove).isFalse(); } @Test public void 포는_다리가_되는_기물이_포이면_지나갈수_없다(){ MoveStrategy moveStrategy = new CannonMoveStrategy(); + Route route = new Route(Position.of(4, 4), Position.of(1, 4), List.of(Position.of(3, 4), Position.of(2, 4))); - List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isFalse(); + boolean canMove = moveStrategy.canMove( + route, + List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)), + Optional.empty(), + TeamColor.CHO + ); + assertThat(canMove).isFalse(); } @Test @@ -76,11 +79,13 @@ class 차단검사 { Piece bridgePawn = Piece.of(TeamColor.CHO, PieceType.PAWN); Piece targetCannon = Piece.of(TeamColor.HAN, PieceType.CANNON); - List blocking = List.of(bridgePawn, targetCannon); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isFalse(); + boolean canMove = moveStrategy.canMove( + new Route(Position.of(4, 4), Position.of(1, 4), List.of(Position.of(3, 4), Position.of(2, 4))), + List.of(bridgePawn), + Optional.of(targetCannon), + TeamColor.CHO + ); + assertThat(canMove).isFalse(); } @Test @@ -90,11 +95,13 @@ class 차단검사 { Piece bridgeRook = Piece.of(TeamColor.HAN, PieceType.ROOK); Piece targetHorse = Piece.of(TeamColor.CHO, PieceType.HORSE); - List blocking = List.of(bridgeRook, targetHorse); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isFalse(); + boolean canMove = moveStrategy.canMove( + new Route(Position.of(4, 4), Position.of(1, 4), List.of(Position.of(3, 4), Position.of(2, 4))), + List.of(bridgeRook), + Optional.of(targetHorse), + TeamColor.CHO + ); + assertThat(canMove).isFalse(); } @Test @@ -102,11 +109,14 @@ class 차단검사 { MoveStrategy moveStrategy = new CannonMoveStrategy(); Piece bridgePawn = Piece.of(TeamColor.CHO, PieceType.PAWN); - List blocking = List.of(bridgePawn); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isTrue(); + boolean canMove = moveStrategy.canMove( + new Route(Position.of(4, 4), Position.of(1, 4), List.of(Position.of(3, 4), Position.of(2, 4))), + List.of(bridgePawn), + Optional.empty(), + TeamColor.CHO + ); + assertThat(canMove).isTrue(); } @Test @@ -116,11 +126,13 @@ class 차단검사 { Piece bridgeHorse = Piece.of(TeamColor.CHO, PieceType.HORSE); Piece targetRook = Piece.of(TeamColor.HAN, PieceType.ROOK); - List blocking = List.of(bridgeHorse, targetRook); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); - assertThat(canJumpTo).isTrue(); + boolean canMove = moveStrategy.canMove( + new Route(Position.of(4, 4), Position.of(1, 4), List.of(Position.of(3, 4), Position.of(2, 4))), + List.of(bridgeHorse), + Optional.of(targetRook), + TeamColor.CHO + ); + assertThat(canMove).isTrue(); } } } diff --git a/src/test/java/strategy/move/ElephantMoveStrategyTest.java b/src/test/java/strategy/move/ElephantMoveStrategyTest.java index 39b82458a0..9499b2754e 100644 --- a/src/test/java/strategy/move/ElephantMoveStrategyTest.java +++ b/src/test/java/strategy/move/ElephantMoveStrategyTest.java @@ -1,6 +1,5 @@ package strategy.move; -import domain.BlockingPieces; import domain.Direction; import domain.MovePath; import domain.Piece; @@ -9,6 +8,7 @@ import domain.Route; import domain.TeamColor; import java.util.List; +import java.util.Optional; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -50,22 +50,26 @@ class 차단검사 { @Test public void 상은_장애물이_없으면_지나갈수_있다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); + Route route = new Route(Position.of(4, 4), Position.of(1, 2), List.of(Position.of(3, 4), Position.of(2, 3))); - List blocking = List.of(); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + boolean canMove = moveStrategy.canMove(route, List.of(), Optional.empty(), TeamColor.CHO); - assertThat(canJumpTo).isTrue(); + assertThat(canMove).isTrue(); } @Test public void 상은_장애물이_하나라도_있으면_지나갈수_없다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); - List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + Route route = new Route(Position.of(4, 4), Position.of(1, 2), List.of(Position.of(3, 4), Position.of(2, 3))); - assertThat(canJumpTo).isFalse(); + boolean canMove = moveStrategy.canMove( + route, + List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)), + Optional.empty(), + TeamColor.CHO + ); + + assertThat(canMove).isFalse(); } } diff --git a/src/test/java/strategy/move/GuardMoveStrategyTest.java b/src/test/java/strategy/move/GuardMoveStrategyTest.java index 5304ccb176..4acc1d16ae 100644 --- a/src/test/java/strategy/move/GuardMoveStrategyTest.java +++ b/src/test/java/strategy/move/GuardMoveStrategyTest.java @@ -1,6 +1,5 @@ package strategy.move; -import domain.BlockingPieces; import domain.Direction; import domain.MovePath; import domain.Piece; @@ -9,6 +8,7 @@ import domain.Route; import domain.TeamColor; import java.util.List; +import java.util.Optional; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -60,23 +60,26 @@ class 차단검사 { @Test public void 사는_장애물이_없으면_지나갈수_있다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); + Route route = new Route(Position.of(1, 4), Position.of(0, 4), List.of()); - List blocking = List.of(); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + boolean canMove = moveStrategy.canMove(route, List.of(), Optional.empty(), TeamColor.CHO); - assertThat(canJumpTo).isTrue(); + assertThat(canMove).isTrue(); } @Test public void 사는_장애물이_하나라도_있으면_지나갈수_없다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); + Route route = new Route(Position.of(1, 4), Position.of(0, 4), List.of()); - List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + boolean canMove = moveStrategy.canMove( + route, + List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)), + Optional.empty(), + TeamColor.CHO + ); - assertThat(canJumpTo).isFalse(); + assertThat(canMove).isFalse(); } } diff --git a/src/test/java/strategy/move/HorseMoveStrategyTest.java b/src/test/java/strategy/move/HorseMoveStrategyTest.java index c2fe153370..6ac7494f3a 100644 --- a/src/test/java/strategy/move/HorseMoveStrategyTest.java +++ b/src/test/java/strategy/move/HorseMoveStrategyTest.java @@ -1,6 +1,5 @@ package strategy.move; -import domain.BlockingPieces; import domain.Direction; import domain.MovePath; import domain.Piece; @@ -9,6 +8,7 @@ import domain.Route; import domain.TeamColor; import java.util.List; +import java.util.Optional; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -60,23 +60,26 @@ class 차단검사 { @Test public void 마는_장애물이_없으면_지나갈수_있다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); + Route route = new Route(Position.of(4, 4), Position.of(2, 3), List.of(Position.of(3, 4))); - List blocking= List.of(); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + boolean canMove = moveStrategy.canMove(route, List.of(), Optional.empty(), TeamColor.CHO); - assertThat(canJumpTo).isTrue(); + assertThat(canMove).isTrue(); } @Test public void 마는_장애물이_하나라도_있으면_지나갈수_없다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); + Route route = new Route(Position.of(4, 4), Position.of(2, 3), List.of(Position.of(3, 4))); - List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + boolean canMove = moveStrategy.canMove( + route, + List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)), + Optional.empty(), + TeamColor.CHO + ); - assertThat(canJumpTo).isFalse(); + assertThat(canMove).isFalse(); } } diff --git a/src/test/java/strategy/move/KingMoveStrategyTest.java b/src/test/java/strategy/move/KingMoveStrategyTest.java index f27f6024b6..fcc12cf6a9 100644 --- a/src/test/java/strategy/move/KingMoveStrategyTest.java +++ b/src/test/java/strategy/move/KingMoveStrategyTest.java @@ -1,6 +1,5 @@ package strategy.move; -import domain.BlockingPieces; import domain.Direction; import domain.MovePath; import domain.Piece; @@ -9,6 +8,7 @@ import domain.Route; import domain.TeamColor; import java.util.List; +import java.util.Optional; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -60,23 +60,26 @@ class 차단검사 { @Test public void 왕은_장애물이_없으면_지나갈수_있다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); + Route route = new Route(Position.of(1, 4), Position.of(0, 4), List.of()); - List blocking = List.of(); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + boolean canMove = moveStrategy.canMove(route, List.of(), Optional.empty(), TeamColor.CHO); - assertThat(canJumpTo).isTrue(); + assertThat(canMove).isTrue(); } @Test public void 왕은_장애물이_하나라도_있으면_지나갈수_없다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); + Route route = new Route(Position.of(1, 4), Position.of(0, 4), List.of()); - List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + boolean canMove = moveStrategy.canMove( + route, + List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)), + Optional.empty(), + TeamColor.CHO + ); - assertThat(canJumpTo).isFalse(); + assertThat(canMove).isFalse(); } } diff --git a/src/test/java/strategy/move/PawnMoveStrategyTest.java b/src/test/java/strategy/move/PawnMoveStrategyTest.java index da476ed908..13037f2894 100644 --- a/src/test/java/strategy/move/PawnMoveStrategyTest.java +++ b/src/test/java/strategy/move/PawnMoveStrategyTest.java @@ -1,6 +1,5 @@ package strategy.move; -import domain.BlockingPieces; import domain.Direction; import domain.MovePath; import domain.Piece; @@ -9,6 +8,7 @@ import domain.Route; import domain.TeamColor; import java.util.List; +import java.util.Optional; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -81,23 +81,26 @@ class 차단검사 { @Test public void 졸은_장애물이_없으면_지나갈수_있다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); + Route route = new Route(Position.of(4, 4), Position.of(3, 4), List.of()); - List blocking = List.of(); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + boolean canMove = moveStrategy.canMove(route, List.of(), Optional.empty(), TeamColor.CHO); - assertThat(canJumpTo).isTrue(); + assertThat(canMove).isTrue(); } @Test public void 졸은_장애물이_하나라도_있으면_지나갈수_없다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); + Route route = new Route(Position.of(4, 4), Position.of(3, 4), List.of()); - List blocking = List.of(Piece.of(TeamColor.CHO,PieceType.CANNON)); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + boolean canMove = moveStrategy.canMove( + route, + List.of(Piece.of(TeamColor.CHO,PieceType.CANNON)), + Optional.empty(), + TeamColor.CHO + ); - assertThat(canJumpTo).isFalse(); + assertThat(canMove).isFalse(); } } } diff --git a/src/test/java/strategy/move/RookMoveStrategyTest.java b/src/test/java/strategy/move/RookMoveStrategyTest.java index a01d49c4f8..afd41b404f 100644 --- a/src/test/java/strategy/move/RookMoveStrategyTest.java +++ b/src/test/java/strategy/move/RookMoveStrategyTest.java @@ -1,12 +1,14 @@ package strategy.move; -import domain.BlockingPieces; import domain.Direction; import domain.MovePath; import domain.Piece; import domain.PieceType; +import domain.Position; +import domain.Route; import domain.TeamColor; import java.util.List; +import java.util.Optional; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -50,23 +52,26 @@ class 차단검사 { @Test public void 차는_장애물이_없으면_지나갈수_있다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); + Route route = new Route(Position.of(4, 4), Position.of(3, 4), List.of()); - List blocking = List.of(); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + boolean canMove = moveStrategy.canMove(route, List.of(), Optional.empty(), TeamColor.CHO); - assertThat(canJumpTo).isTrue(); + assertThat(canMove).isTrue(); } @Test public void 차는_장애물이_하나라도_있으면_지나갈수_없다(){ MoveStrategy moveStrategy = new PawnMoveStrategy(); + Route route = new Route(Position.of(4, 4), Position.of(3, 4), List.of()); - List blocking = List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)); - BlockingPieces blockingPieces = new BlockingPieces(blocking); - boolean canJumpTo = moveStrategy.canJump(blockingPieces, TeamColor.CHO); + boolean canMove = moveStrategy.canMove( + route, + List.of(Piece.of(TeamColor.CHO, PieceType.CANNON)), + Optional.empty(), + TeamColor.CHO + ); - assertThat(canJumpTo).isFalse(); + assertThat(canMove).isFalse(); } } } From d3c4ef1be7a137e1242a5888de99070df51d37e5 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 21:33:20 +0900 Subject: [PATCH 55/82] feat: add console views --- src/main/java/Runner.java | 4 ++ src/main/java/domain/Position.java | 13 +++- src/main/java/io/InputView.java | 33 ++++++++++ src/main/java/io/OutputView.java | 102 +++++++++++++++++++++++++++++ 4 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 src/main/java/Runner.java create mode 100644 src/main/java/io/InputView.java create mode 100644 src/main/java/io/OutputView.java diff --git a/src/main/java/Runner.java b/src/main/java/Runner.java new file mode 100644 index 0000000000..1cc70d74e2 --- /dev/null +++ b/src/main/java/Runner.java @@ -0,0 +1,4 @@ +package PACKAGE_NAME; + +public class Runner { +} diff --git a/src/main/java/domain/Position.java b/src/main/java/domain/Position.java index 8c69a1d78d..b08b14106d 100644 --- a/src/main/java/domain/Position.java +++ b/src/main/java/domain/Position.java @@ -21,6 +21,14 @@ public static Position of(int row, int column) { return new Position(new Row(row), new Column(column)); } + public int row() { + return row.value(); + } + + public int column() { + return column.value(); + } + @Override public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { @@ -35,6 +43,9 @@ public int hashCode() { return Objects.hash(row, column); } - + @Override + public String toString() { + return "(" + row() + "," + column() + ")"; + } } diff --git a/src/main/java/io/InputView.java b/src/main/java/io/InputView.java new file mode 100644 index 0000000000..b87c5f74b3 --- /dev/null +++ b/src/main/java/io/InputView.java @@ -0,0 +1,33 @@ +package io; + +import domain.TeamColor; +import java.util.Scanner; + +public class InputView { + + private final Scanner scanner; + + public InputView() { + this(new Scanner(System.in)); + } + + public InputView(Scanner scanner) { + this.scanner = scanner; + } + + public int readFormationChoice(TeamColor teamColor) { + System.out.print(teamColor + " 상차림 선택 (1. 안상 2. 바깥상 3. 좌상 4. 우상) > "); + return Integer.parseInt(scanner.nextLine().trim()); + } + + public int readPieceChoice(TeamColor teamColor) { + System.out.print(teamColor + " 차례, 선택할 기물 번호 > "); + return Integer.parseInt(scanner.nextLine().trim()); + } + + public int readRouteChoice() { + System.out.print("이동할 경로 번호 선택 (0은 뒤로가기) > "); + return Integer.parseInt(scanner.nextLine().trim()); + } + +} diff --git a/src/main/java/io/OutputView.java b/src/main/java/io/OutputView.java new file mode 100644 index 0000000000..c1886088a9 --- /dev/null +++ b/src/main/java/io/OutputView.java @@ -0,0 +1,102 @@ +package io; + +import domain.Board; +import domain.Piece; +import domain.PieceType; +import domain.Position; +import domain.Route; +import domain.TeamColor; +import java.util.List; +import java.util.Map; + +public class OutputView { + + private static final String CHO_COLOR = "\u001B[38;5;71m"; + private static final String HAN_COLOR = "\u001B[38;5;167m"; + private static final String RESET = "\u001B[0m"; + + public void printGameStart() { + System.out.println("장기 게임을 시작합니다."); + } + + public void printFormationSelectionPrompt(TeamColor teamColor) { + System.out.println(teamColor + " 상차림을 선택하세요."); + System.out.println("1. 안상차림"); + System.out.println("2. 바깥상차림"); + System.out.println("3. 좌상차림"); + System.out.println("4. 우상차림"); + } + + public void printCurrentTurn(TeamColor teamColor) { + System.out.println(); + System.out.println("현재 턴: " + teamColor); + } + + public void printPieceOptions(List> pieces) { + System.out.println("선택 가능한 기물:"); + for (int index = 0; index < pieces.size(); index++) { + Map.Entry entry = pieces.get(index); + System.out.println((index + 1) + ". " + formatPiece(entry.getValue()) + entry.getKey()); + } + } + + public void printRouteOptions(List routes) { + System.out.println("이동 가능한 경로:"); + System.out.println("0. 뒤로가기"); + for (int index = 0; index < routes.size(); index++) { + Route route = routes.get(index); + System.out.println((index + 1) + ". " + route.startPos() + " -> " + route.endPos()); + } + } + + public void printBoard(Board board) { + System.out.println(); + System.out.println("현재 장기판"); + System.out.println(" 0 1 2 3 4 5 6 7 8"); + for (int row = 0; row <= 8; row++) { + StringBuilder line = new StringBuilder(); + line.append(row).append(" | "); + for (int column = 0; column <= 9; column++) { + Piece piece = board.findPiece(Position.of(row, column)).orElse(null); + line.append(formatBoardCell(piece)).append(" "); + } + System.out.println(line); + } + } + + public void printMoveResult(Piece piece, Position destination) { + System.out.println(formatPiece(piece) + " 가 " + destination + " 로 이동했습니다."); + } + + private String formatBoardCell(Piece piece) { + if (piece == null) { + return " . "; + } + String symbol = switch (piece.getPieceType()) { + case ROOK -> "차"; + case HORSE -> "마"; + case ELEPHANT -> "상"; + case GUARD -> "사"; + case KING -> "왕"; + case CANNON -> "포"; + case PAWN -> "졸"; + }; + + if (piece.getTeamColor() == TeamColor.CHO) { + return CHO_COLOR + symbol + RESET; + } + return HAN_COLOR + symbol + RESET; + } + + private String formatPiece(Piece piece) { + return switch (piece.getPieceType()) { + case ROOK -> "차"; + case HORSE -> "마"; + case ELEPHANT -> "상"; + case GUARD -> "사"; + case KING -> "왕"; + case CANNON -> "포"; + case PAWN -> piece.getTeamColor() == TeamColor.CHO ? "졸" : "병"; + }; + } +} From 7de0df0f3ea1ce70e38b5a80862bc9d851ba8eb6 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 21:39:45 +0900 Subject: [PATCH 56/82] feat: add board queries for runner flow --- src/main/java/domain/Board.java | 22 ++++++++++++++++++++++ src/test/java/domain/BoardTest.java | 21 +++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index 4aea9eb480..a4ecbb1bad 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -35,6 +35,28 @@ public Optional findPiece(Position position) { return Optional.ofNullable(pieces.get(position)); } + public List> findPiecesByTeam(TeamColor teamColor) { + return pieces.entrySet().stream() + .filter(entry -> entry.getValue().getTeamColor() == teamColor) + .sorted((left, right) -> { + int rowCompare = Integer.compare(left.getKey().row(), right.getKey().row()); + if (rowCompare != 0) { + return rowCompare; + } + return Integer.compare(left.getKey().column(), right.getKey().column()); + }) + .toList(); + } + + public List findMovableRoutes(Piece piece) { + Position currentPosition = findPositionOf(piece) + .orElseThrow(() -> new IllegalArgumentException("보드에 없는 기물입니다.")); + + return piece.makeRoutes(currentPosition).stream() + .filter(route -> piece.canMove(route, getBlockingPieces(route), getDestinationPiece(route))) + .toList(); + } + public void move(Piece piece, Position destination) { Position currentPosition = findPositionOf(piece) .orElseThrow(() -> new IllegalArgumentException("보드에 없는 기물입니다.")); diff --git a/src/test/java/domain/BoardTest.java b/src/test/java/domain/BoardTest.java index 13e9ee693f..85a8ca04e4 100644 --- a/src/test/java/domain/BoardTest.java +++ b/src/test/java/domain/BoardTest.java @@ -69,6 +69,13 @@ class 위치조회 { void 특정_기물의_현재_위치를_찾는다() { assertThat(board.findPositionOf(hanHorse)).contains(Position.of(2, 4)); } + + @Test + void 팀에_속한_기물들을_좌표순으로_조회한다() { + assertThat(board.findPiecesByTeam(TeamColor.CHO)) + .extracting(entry -> entry.getKey()) + .containsExactly(Position.of(1, 4), Position.of(3, 4)); + } } @Nested @@ -86,5 +93,19 @@ class 이동 { assertThat(movableBoard.findPiece(Position.of(4, 4))).isEmpty(); assertThat(movableBoard.findPiece(Position.of(3, 4))).contains(movingPawn); } + + @Test + void 현재_판_상태를_기준으로_기물의_이동_가능_경로를_반환한다() { + Piece movingPawn = Piece.of(TeamColor.CHO, PieceType.PAWN); + Piece allyPiece = Piece.of(TeamColor.CHO, PieceType.GUARD); + Board movableBoard = new Board(Map.of( + Position.of(4, 4), movingPawn, + Position.of(4, 5), allyPiece + )); + + assertThat(movableBoard.findMovableRoutes(movingPawn)) + .extracting(Route::endPos) + .containsExactlyInAnyOrder(Position.of(3, 4), Position.of(4, 3)); + } } } From c2bd57a4a4699235742ae00523369d63be9f5f0e Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 21:41:49 +0900 Subject: [PATCH 57/82] feat: implement runner game loop --- src/main/java/Runner.java | 115 ++++++++++++++++++++++++++++- src/main/java/domain/Board.java | 1 + src/main/java/domain/Position.java | 4 + src/main/java/io/OutputView.java | 4 + 4 files changed, 123 insertions(+), 1 deletion(-) diff --git a/src/main/java/Runner.java b/src/main/java/Runner.java index 1cc70d74e2..35c596a212 100644 --- a/src/main/java/Runner.java +++ b/src/main/java/Runner.java @@ -1,4 +1,117 @@ -package PACKAGE_NAME; +import domain.Board; +import domain.InitialGameState; +import domain.Piece; +import domain.Position; +import domain.TeamColor; +import domain.TurnManager; +import io.InputView; +import io.OutputView; +import java.util.List; +import java.util.Map; +import strategy.formation.InitialFormationStrategy; +import strategy.formation.InnerFormationStrategy; +import strategy.formation.LeftFormationStrategy; +import strategy.formation.OuterFormationStrategy; +import strategy.formation.RightFormationStrategy; public class Runner { + + private final InputView inputView; + private final OutputView outputView; + private final TurnManager turnManager; + + public Runner() { + this(new InputView(), new OutputView(), new TurnManager()); + } + + public Runner(InputView inputView, OutputView outputView, TurnManager turnManager) { + this.inputView = inputView; + this.outputView = outputView; + this.turnManager = turnManager; + } + + public void run() { + outputView.printGameStart(); + + InitialFormationStrategy choStrategy = chooseFormationStrategy(TeamColor.CHO); + InitialFormationStrategy hanStrategy = chooseFormationStrategy(TeamColor.HAN); + + Initializer initializer = new Initializer(choStrategy, hanStrategy); + InitialGameState initialGameState = initializer.initialize(); + Board board = new Board(initialGameState.boardState()); + + outputView.printBoard(board); + + while (true) { + playTurn(board); + } + } + + private InitialFormationStrategy chooseFormationStrategy(TeamColor teamColor) { + while (true) { + outputView.printFormationSelectionPrompt(teamColor); + try { + int choice = inputView.readFormationChoice(teamColor); + return switch (choice) { + case 1 -> new InnerFormationStrategy(); + case 2 -> new OuterFormationStrategy(); + case 3 -> new LeftFormationStrategy(); + case 4 -> new RightFormationStrategy(); + default -> throw new IllegalArgumentException("상차림 번호는 1~4 사이여야 합니다."); + }; + } catch (RuntimeException exception) { + outputView.printError("상차림 입력이 올바르지 않습니다."); + } + } + } + + private void playTurn(Board board) { + TeamColor currentTurn = turnManager.getCurrentTurn(); + outputView.printCurrentTurn(currentTurn); + outputView.printBoard(board); + + while (true) { + try { + List> pieces = board.findPiecesByTeam(currentTurn); + outputView.printPieceOptions(pieces); + + int pieceChoice = inputView.readPieceChoice(currentTurn); + Piece selectedPiece = getSelectedPiece(pieces, pieceChoice); + + List routes = board.findMovableRoutes(selectedPiece); + if (routes.isEmpty()) { + throw new IllegalArgumentException("선택한 기물은 이동 가능한 경로가 없습니다."); + } + + outputView.printRouteOptions(routes); + int routeChoice = inputView.readRouteChoice(); + + if (routeChoice == 0) { + continue; + } + + Position destination = getSelectedRoute(routes, routeChoice).endPos(); + board.move(selectedPiece, destination); + outputView.printMoveResult(selectedPiece, destination); + turnManager.progressTurn(); + return; + } catch (RuntimeException exception) { + outputView.printError(exception.getMessage()); + } + } + } + + private Piece getSelectedPiece(List> pieces, int pieceChoice) { + if (pieceChoice < 1 || pieceChoice > pieces.size()) { + throw new IllegalArgumentException("기물 번호가 범위를 벗어났습니다."); + } + return pieces.get(pieceChoice - 1).getValue(); + } + + private domain.Route getSelectedRoute(List routes, int routeChoice) { + if (routeChoice < 1 || routeChoice > routes.size()) { + throw new IllegalArgumentException("경로 번호가 범위를 벗어났습니다."); + } + return routes.get(routeChoice - 1); + } } diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index a4ecbb1bad..a116bd6515 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -53,6 +53,7 @@ public List findMovableRoutes(Piece piece) { .orElseThrow(() -> new IllegalArgumentException("보드에 없는 기물입니다.")); return piece.makeRoutes(currentPosition).stream() + .filter(route -> route.endPos().isInsideBoard()) .filter(route -> piece.canMove(route, getBlockingPieces(route), getDestinationPiece(route))) .toList(); } diff --git a/src/main/java/domain/Position.java b/src/main/java/domain/Position.java index b08b14106d..8928465ddf 100644 --- a/src/main/java/domain/Position.java +++ b/src/main/java/domain/Position.java @@ -29,6 +29,10 @@ public int column() { return column.value(); } + public boolean isInsideBoard() { + return row() >= 0 && row() <= 8 && column() >= 0 && column() <= 9; + } + @Override public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { diff --git a/src/main/java/io/OutputView.java b/src/main/java/io/OutputView.java index c1886088a9..339e6c033c 100644 --- a/src/main/java/io/OutputView.java +++ b/src/main/java/io/OutputView.java @@ -68,6 +68,10 @@ public void printMoveResult(Piece piece, Position destination) { System.out.println(formatPiece(piece) + " 가 " + destination + " 로 이동했습니다."); } + public void printError(String message) { + System.out.println("[오류] " + message); + } + private String formatBoardCell(Piece piece) { if (piece == null) { return " . "; From db83c7eca83e0de084ef469724107e1b9c2de619 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 21:45:58 +0900 Subject: [PATCH 58/82] feat: add application entry point --- src/main/java/Main.java | 6 ++++++ src/main/java/io/OutputView.java | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 src/main/java/Main.java diff --git a/src/main/java/Main.java b/src/main/java/Main.java new file mode 100644 index 0000000000..f38d90dff8 --- /dev/null +++ b/src/main/java/Main.java @@ -0,0 +1,6 @@ +public class Main { + + public static void main(String[] args) { + new Runner().run(); + } +} diff --git a/src/main/java/io/OutputView.java b/src/main/java/io/OutputView.java index 339e6c033c..7642021e09 100644 --- a/src/main/java/io/OutputView.java +++ b/src/main/java/io/OutputView.java @@ -52,7 +52,7 @@ public void printRouteOptions(List routes) { public void printBoard(Board board) { System.out.println(); System.out.println("현재 장기판"); - System.out.println(" 0 1 2 3 4 5 6 7 8"); + System.out.println(" 0 1 2 3 4 5 6 7 8 9"); for (int row = 0; row <= 8; row++) { StringBuilder line = new StringBuilder(); line.append(row).append(" | "); From c044e3bed401e4936d3b944ba162326c3218ea76 Mon Sep 17 00:00:00 2001 From: KIM SEON WOO Date: Fri, 27 Mar 2026 22:15:21 +0900 Subject: [PATCH 59/82] =?UTF-8?q?refactor:=20view=20=EB=82=B4=EC=9A=A9=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/Runner.java | 20 ++-- src/main/java/domain/Piece.java | 31 ++++-- src/main/java/domain/TeamColor.java | 9 +- src/main/java/io/InputView.java | 4 +- src/main/java/io/OutputView.java | 94 +++++++++++++------ src/main/java/strategy/move/MoveStrategy.java | 10 +- 6 files changed, 120 insertions(+), 48 deletions(-) diff --git a/src/main/java/Runner.java b/src/main/java/Runner.java index 35c596a212..46d445083c 100644 --- a/src/main/java/Runner.java +++ b/src/main/java/Runner.java @@ -52,13 +52,19 @@ private InitialFormationStrategy chooseFormationStrategy(TeamColor teamColor) { outputView.printFormationSelectionPrompt(teamColor); try { int choice = inputView.readFormationChoice(teamColor); - return switch (choice) { - case 1 -> new InnerFormationStrategy(); - case 2 -> new OuterFormationStrategy(); - case 3 -> new LeftFormationStrategy(); - case 4 -> new RightFormationStrategy(); - default -> throw new IllegalArgumentException("상차림 번호는 1~4 사이여야 합니다."); - }; + if (choice == 1) { + return new InnerFormationStrategy(); + } + if (choice == 2) { + return new OuterFormationStrategy(); + } + if (choice == 3) { + return new LeftFormationStrategy(); + } + if (choice == 4) { + return new RightFormationStrategy(); + } + throw new IllegalArgumentException("상차림 번호는 1~4 사이여야 합니다."); } catch (RuntimeException exception) { outputView.printError("상차림 입력이 올바르지 않습니다."); } diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/Piece.java index c75c9596ca..bb00aa25a3 100644 --- a/src/main/java/domain/Piece.java +++ b/src/main/java/domain/Piece.java @@ -43,14 +43,27 @@ public static Piece of(TeamColor teamColor, PieceType pieceType) { } private static MoveStrategy createMoveStrategy(PieceType pieceType) { - return switch (pieceType) { - case CANNON -> new CannonMoveStrategy(); - case ELEPHANT -> new ElephantMoveStrategy(); - case GUARD -> new GuardMoveStrategy(); - case HORSE -> new HorseMoveStrategy(); - case KING -> new KingMoveStrategy(); - case PAWN -> new PawnMoveStrategy(); - case ROOK -> new RookMoveStrategy(); - }; + if (pieceType == PieceType.CANNON) { + return new CannonMoveStrategy(); + } + if (pieceType == PieceType.ELEPHANT) { + return new ElephantMoveStrategy(); + } + if (pieceType == PieceType.GUARD) { + return new GuardMoveStrategy(); + } + if (pieceType == PieceType.HORSE) { + return new HorseMoveStrategy(); + } + if (pieceType == PieceType.KING) { + return new KingMoveStrategy(); + } + if (pieceType == PieceType.PAWN) { + return new PawnMoveStrategy(); + } + if (pieceType == PieceType.ROOK) { + return new RookMoveStrategy(); + } + throw new IllegalArgumentException("지원하지 않는 기물 타입입니다."); } } diff --git a/src/main/java/domain/TeamColor.java b/src/main/java/domain/TeamColor.java index 97318428bb..d75ec36e4c 100644 --- a/src/main/java/domain/TeamColor.java +++ b/src/main/java/domain/TeamColor.java @@ -2,5 +2,12 @@ public enum TeamColor { CHO, - HAN + HAN; + + public String displayName() { + if (this == CHO) { + return "초"; + } + return "한"; + } } diff --git a/src/main/java/io/InputView.java b/src/main/java/io/InputView.java index b87c5f74b3..eb844b3aa8 100644 --- a/src/main/java/io/InputView.java +++ b/src/main/java/io/InputView.java @@ -16,12 +16,12 @@ public InputView(Scanner scanner) { } public int readFormationChoice(TeamColor teamColor) { - System.out.print(teamColor + " 상차림 선택 (1. 안상 2. 바깥상 3. 좌상 4. 우상) > "); + System.out.print(teamColor.displayName() + " 상차림 선택 (1. 안상 2. 바깥상 3. 좌상 4. 우상) > "); return Integer.parseInt(scanner.nextLine().trim()); } public int readPieceChoice(TeamColor teamColor) { - System.out.print(teamColor + " 차례, 선택할 기물 번호 > "); + System.out.print(teamColor.displayName() + " 차례, 선택할 기물 번호 > "); return Integer.parseInt(scanner.nextLine().trim()); } diff --git a/src/main/java/io/OutputView.java b/src/main/java/io/OutputView.java index 7642021e09..1ebdcd7c11 100644 --- a/src/main/java/io/OutputView.java +++ b/src/main/java/io/OutputView.java @@ -20,7 +20,7 @@ public void printGameStart() { } public void printFormationSelectionPrompt(TeamColor teamColor) { - System.out.println(teamColor + " 상차림을 선택하세요."); + System.out.println(teamColor.displayName() + " 상차림을 선택하세요."); System.out.println("1. 안상차림"); System.out.println("2. 바깥상차림"); System.out.println("3. 좌상차림"); @@ -29,7 +29,7 @@ public void printFormationSelectionPrompt(TeamColor teamColor) { public void printCurrentTurn(TeamColor teamColor) { System.out.println(); - System.out.println("현재 턴: " + teamColor); + System.out.println("현재 턴: " + teamColor.displayName()); } public void printPieceOptions(List> pieces) { @@ -52,16 +52,21 @@ public void printRouteOptions(List routes) { public void printBoard(Board board) { System.out.println(); System.out.println("현재 장기판"); - System.out.println(" 0 1 2 3 4 5 6 7 8 9"); - for (int row = 0; row <= 8; row++) { + System.out.println(" 0 1 2 3 4 5 6 7 8"); + System.out.println(" ┌────┬────┬────┬────┬────┬────┬────┬────┬────┐"); + for (int column = 0; column <= 9; column++) { StringBuilder line = new StringBuilder(); - line.append(row).append(" | "); - for (int column = 0; column <= 9; column++) { + line.append(String.format("%2d │", column)); + for (int row = 0; row <= 8; row++) { Piece piece = board.findPiece(Position.of(row, column)).orElse(null); - line.append(formatBoardCell(piece)).append(" "); + line.append(" ").append(formatBoardCell(piece)).append(" │"); } System.out.println(line); + if (column < 9) { + System.out.println(" ├────┼────┼────┼────┼────┼────┼────┼────┼────┤"); + } } + System.out.println(" └────┴────┴────┴────┴────┴────┴────┴────┴────┘"); } public void printMoveResult(Piece piece, Position destination) { @@ -69,22 +74,14 @@ public void printMoveResult(Piece piece, Position destination) { } public void printError(String message) { - System.out.println("[오류] " + message); + System.out.println("[ERROR] " + message); } private String formatBoardCell(Piece piece) { if (piece == null) { - return " . "; - } - String symbol = switch (piece.getPieceType()) { - case ROOK -> "차"; - case HORSE -> "마"; - case ELEPHANT -> "상"; - case GUARD -> "사"; - case KING -> "왕"; - case CANNON -> "포"; - case PAWN -> "졸"; - }; + return " "; + } + String symbol = formatBoardSymbol(piece); if (piece.getTeamColor() == TeamColor.CHO) { return CHO_COLOR + symbol + RESET; @@ -93,14 +90,55 @@ private String formatBoardCell(Piece piece) { } private String formatPiece(Piece piece) { - return switch (piece.getPieceType()) { - case ROOK -> "차"; - case HORSE -> "마"; - case ELEPHANT -> "상"; - case GUARD -> "사"; - case KING -> "왕"; - case CANNON -> "포"; - case PAWN -> piece.getTeamColor() == TeamColor.CHO ? "졸" : "병"; - }; + if (piece.getPieceType() == PieceType.ROOK) { + return "차"; + } + if (piece.getPieceType() == PieceType.HORSE) { + return "마"; + } + if (piece.getPieceType() == PieceType.ELEPHANT) { + return "상"; + } + if (piece.getPieceType() == PieceType.GUARD) { + return "사"; + } + if (piece.getPieceType() == PieceType.KING) { + return "왕"; + } + if (piece.getPieceType() == PieceType.CANNON) { + return "포"; + } + if (piece.getPieceType() == PieceType.PAWN && piece.getTeamColor() == TeamColor.CHO) { + return "졸"; + } + if (piece.getPieceType() == PieceType.PAWN) { + return "병"; + } + throw new IllegalArgumentException("지원하지 않는 기물 타입입니다."); + } + + private String formatBoardSymbol(Piece piece) { + if (piece.getPieceType() == PieceType.ROOK) { + return "차"; + } + if (piece.getPieceType() == PieceType.HORSE) { + return "마"; + } + if (piece.getPieceType() == PieceType.ELEPHANT) { + return "상"; + } + if (piece.getPieceType() == PieceType.GUARD) { + return "사"; + } + if (piece.getPieceType() == PieceType.KING) { + return "왕"; + } + if (piece.getPieceType() == PieceType.CANNON) { + return "포"; + } + if (piece.getPieceType() == PieceType.PAWN) { + return "졸"; + } + throw new IllegalArgumentException("지원하지 않는 기물 타입입니다."); } } diff --git a/src/main/java/strategy/move/MoveStrategy.java b/src/main/java/strategy/move/MoveStrategy.java index 202da282fc..543427774b 100644 --- a/src/main/java/strategy/move/MoveStrategy.java +++ b/src/main/java/strategy/move/MoveStrategy.java @@ -25,12 +25,20 @@ default List makeRoutes(Position curPos, TeamColor teamColor) { for (int i = 0; i < steps.size(); i++) { - currentPos = currentPos.next(steps.get(i)); + try { + currentPos = currentPos.next(steps.get(i)); + } catch (IllegalArgumentException exception) { + currentPos = null; + break; + } if (i < steps.size() - 1) { intermediates.add(currentPos); } } + if (currentPos == null) { + continue; + } validRoutes.add(new Route(curPos, currentPos, intermediates)); } From 3f196c705bd805be642da4bd04263f2e78863b7a Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Fri, 27 Mar 2026 23:47:32 +0900 Subject: [PATCH 60/82] =?UTF-8?q?fix:=20=EC=B0=A8,=20=ED=8F=AC=20=ED=95=9C?= =?UTF-8?q?=20=EC=B9=B8=EB=A7=8C=20=EC=9D=B4=EB=8F=99=20=EA=B0=80=EB=8A=A5?= =?UTF-8?q?=ED=95=9C=20=EC=83=81=ED=83=9C=EC=97=90=EC=84=9C,=20=EB=8F=99?= =?UTF-8?q?=EC=84=9C=EB=82=A8=EB=B6=81=20=EC=A7=81=EC=84=A0=20=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=B4=EB=93=9C=20=EB=81=9D=EA=B9=8C=EC=A7=80=20?= =?UTF-8?q?=ED=83=90=EC=83=89=20=EA=B0=80=EB=8A=A5=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../strategy/move/CannonMoveStrategy.java | 31 ++++++++++++------- .../java/strategy/move/RookMoveStrategy.java | 27 +++++++++++----- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/main/java/strategy/move/CannonMoveStrategy.java b/src/main/java/strategy/move/CannonMoveStrategy.java index 3984af625f..4bf36c9d4c 100644 --- a/src/main/java/strategy/move/CannonMoveStrategy.java +++ b/src/main/java/strategy/move/CannonMoveStrategy.java @@ -6,29 +6,36 @@ import domain.PieceType; import domain.Route; import domain.TeamColor; +import java.util.ArrayList; import java.util.List; import java.util.Optional; public class CannonMoveStrategy implements MoveStrategy { - private static final List PATHS = List.of( - new MovePath(List.of(Direction.NORTH)), - new MovePath(List.of(Direction.SOUTH)), - new MovePath(List.of(Direction.EAST)), - new MovePath(List.of(Direction.WEST)) - ); - @Override public List getPaths(TeamColor teamColor) { - return PATHS; + List paths = new ArrayList<>(); + + addStraightPaths(paths, Direction.NORTH); + addStraightPaths(paths, Direction.SOUTH); + addStraightPaths(paths, Direction.EAST); + addStraightPaths(paths, Direction.WEST); + + return paths; } - @Override - public boolean canMove(Route route, List blockingPieces, Optional destinationPiece, TeamColor myTeam) { - if (blockingPieces.isEmpty()) { - return false; + private void addStraightPaths(List paths, Direction direction) { + for (int distance = 1; distance <= 9; distance++) { + List steps = new ArrayList<>(); + for (int i = 0; i < distance; i++) { + steps.add(direction); + } + paths.add(new MovePath(steps)); } + } + @Override + public boolean canMove(Route route, List blockingPieces, Optional destinationPiece, TeamColor myTeam) { if (blockingPieces.size() != 1) { return false; } diff --git a/src/main/java/strategy/move/RookMoveStrategy.java b/src/main/java/strategy/move/RookMoveStrategy.java index 331da83ec6..9dfa1cec8c 100644 --- a/src/main/java/strategy/move/RookMoveStrategy.java +++ b/src/main/java/strategy/move/RookMoveStrategy.java @@ -3,20 +3,31 @@ import domain.Direction; import domain.MovePath; import domain.TeamColor; +import java.util.ArrayList; import java.util.List; public class RookMoveStrategy implements MoveStrategy { - private static final List PATHS = List.of( - new MovePath(List.of(Direction.NORTH)), - new MovePath(List.of(Direction.SOUTH)), - new MovePath(List.of(Direction.EAST)), - new MovePath(List.of(Direction.WEST)) - ); - @Override public List getPaths(TeamColor teamColor) { - return PATHS; + List paths = new ArrayList<>(); + + addStraightPaths(paths, Direction.NORTH); + addStraightPaths(paths, Direction.SOUTH); + addStraightPaths(paths, Direction.EAST); + addStraightPaths(paths, Direction.WEST); + + return paths; + } + + private void addStraightPaths(List paths, Direction direction) { + for (int distance = 1; distance <= 9; distance++) { + List steps = new ArrayList<>(); + for (int i = 0; i < distance; i++) { + steps.add(direction); + } + paths.add(new MovePath(steps)); + } } } From 6f4e223b8a861bf9db3d05405976ce290e160197 Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sat, 28 Mar 2026 00:30:21 +0900 Subject: [PATCH 61/82] =?UTF-8?q?fix:=20=EC=B4=88/=ED=95=9C=20=EC=A1=B8=20?= =?UTF-8?q?=ED=91=9C=EA=B8=B0=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/io/OutputView.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/main/java/io/OutputView.java b/src/main/java/io/OutputView.java index 1ebdcd7c11..a3d61e0c26 100644 --- a/src/main/java/io/OutputView.java +++ b/src/main/java/io/OutputView.java @@ -54,15 +54,15 @@ public void printBoard(Board board) { System.out.println("현재 장기판"); System.out.println(" 0 1 2 3 4 5 6 7 8"); System.out.println(" ┌────┬────┬────┬────┬────┬────┬────┬────┬────┐"); - for (int column = 0; column <= 9; column++) { + for (int row = 0; row <= 9; row++) { StringBuilder line = new StringBuilder(); - line.append(String.format("%2d │", column)); - for (int row = 0; row <= 8; row++) { + line.append(String.format("%2d │", row)); + for (int column = 0; column <= 8; column++) { Piece piece = board.findPiece(Position.of(row, column)).orElse(null); line.append(" ").append(formatBoardCell(piece)).append(" │"); } System.out.println(line); - if (column < 9) { + if (row < 9) { System.out.println(" ├────┼────┼────┼────┼────┼────┼────┼────┼────┤"); } } @@ -108,11 +108,8 @@ private String formatPiece(Piece piece) { if (piece.getPieceType() == PieceType.CANNON) { return "포"; } - if (piece.getPieceType() == PieceType.PAWN && piece.getTeamColor() == TeamColor.CHO) { - return "졸"; - } if (piece.getPieceType() == PieceType.PAWN) { - return "병"; + return "졸"; } throw new IllegalArgumentException("지원하지 않는 기물 타입입니다."); } From 26cfd65eef4b02e0d6a43e9183358ad1ad6c329b Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sat, 28 Mar 2026 01:57:26 +0900 Subject: [PATCH 62/82] =?UTF-8?q?test:=20=EC=B0=A8=20=ED=8F=AC=20=EC=9E=A5?= =?UTF-8?q?=EA=B1=B0=EB=A6=AC=20=EC=9D=B4=EB=8F=99=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=B3=B4=EA=B0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../strategy/move/CannonMoveStrategyTest.java | 63 ++++++++++++++----- .../strategy/move/RookMoveStrategyTest.java | 52 ++++++++++----- 2 files changed, 84 insertions(+), 31 deletions(-) diff --git a/src/test/java/strategy/move/CannonMoveStrategyTest.java b/src/test/java/strategy/move/CannonMoveStrategyTest.java index 30370905fc..44b3e8845e 100644 --- a/src/test/java/strategy/move/CannonMoveStrategyTest.java +++ b/src/test/java/strategy/move/CannonMoveStrategyTest.java @@ -19,30 +19,35 @@ public class CannonMoveStrategyTest { @Nested class 이동경로 { @Test - public void 포는_초나라에서_동서남북_4방향을_가진다() { - MoveStrategy strategy = new RookMoveStrategy(); + public void 포는_초나라에서_동서남북_직선_경로를_보드_끝까지_가진다() { + MoveStrategy strategy = new CannonMoveStrategy(); List paths = strategy.getPaths(TeamColor.CHO); - assertThat(paths).hasSize(4); - assertThat(paths).containsExactlyInAnyOrder( + assertThat(paths).hasSize(36); + assertThat(paths).contains( new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.NORTH, Direction.NORTH, Direction.NORTH, Direction.NORTH)), new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.SOUTH, Direction.SOUTH, Direction.SOUTH, Direction.SOUTH)), new MovePath(List.of(Direction.EAST)), - new MovePath(List.of(Direction.WEST)) + new MovePath(List.of(Direction.EAST, Direction.EAST, Direction.EAST, Direction.EAST)), + new MovePath(List.of(Direction.WEST)), + new MovePath(List.of(Direction.WEST, Direction.WEST, Direction.WEST, Direction.WEST)) ); } @Test - public void 포는_한나라에서_동서남북_4방향을_가진다() { - MoveStrategy strategy = new RookMoveStrategy(); - List paths = strategy.getPaths(TeamColor.HAN); - - assertThat(paths).hasSize(4); - assertThat(paths).containsExactlyInAnyOrder( - new MovePath(List.of(Direction.NORTH)), - new MovePath(List.of(Direction.SOUTH)), - new MovePath(List.of(Direction.EAST)), - new MovePath(List.of(Direction.WEST)) + public void 포는_현재위치에서_여러칸_떨어진_직선_목적지_경로를_생성한다() { + MoveStrategy strategy = new CannonMoveStrategy(); + List routes = strategy.makeRoutes(Position.of(4, 4), TeamColor.HAN); + + assertThat(routes).contains( + new Route(Position.of(4, 4), Position.of(0, 4), + List.of(Position.of(3, 4), Position.of(2, 4), Position.of(1, 4))), + new Route(Position.of(4, 4), Position.of(4, 8), + List.of(Position.of(4, 5), Position.of(4, 6), Position.of(4, 7))), + new Route(Position.of(4, 4), Position.of(8, 4), + List.of(Position.of(5, 4), Position.of(6, 4), Position.of(7, 4))) ); } } @@ -72,6 +77,24 @@ class 차단검사 { assertThat(canMove).isFalse(); } + @Test + public void 포는_다리가_되는_기물이_둘_이상이면_지나갈수_없다() { + MoveStrategy moveStrategy = new CannonMoveStrategy(); + Route route = new Route(Position.of(4, 4), Position.of(0, 4), List.of(Position.of(3, 4), Position.of(2, 4), Position.of(1, 4))); + + boolean canMove = moveStrategy.canMove( + route, + List.of( + Piece.of(TeamColor.CHO, PieceType.PAWN), + Piece.of(TeamColor.HAN, PieceType.HORSE) + ), + Optional.empty(), + TeamColor.CHO + ); + + assertThat(canMove).isFalse(); + } + @Test public void 포는_도착지에_상대방의_포가_있으면_잡을수_없다(){ MoveStrategy moveStrategy = new CannonMoveStrategy(); @@ -134,5 +157,15 @@ class 차단검사 { ); assertThat(canMove).isTrue(); } + + @Test + public void 포는_한칸_이동처럼_중간기물이_없는_경로로는_이동할수_없다() { + MoveStrategy moveStrategy = new CannonMoveStrategy(); + Route route = new Route(Position.of(4, 4), Position.of(3, 4), List.of()); + + boolean canMove = moveStrategy.canMove(route, List.of(), Optional.empty(), TeamColor.CHO); + + assertThat(canMove).isFalse(); + } } } diff --git a/src/test/java/strategy/move/RookMoveStrategyTest.java b/src/test/java/strategy/move/RookMoveStrategyTest.java index afd41b404f..3d2cfd22e3 100644 --- a/src/test/java/strategy/move/RookMoveStrategyTest.java +++ b/src/test/java/strategy/move/RookMoveStrategyTest.java @@ -19,30 +19,35 @@ public class RookMoveStrategyTest { @Nested class 이동경로 { @Test - public void 차는_초나라에서_동서남북_4방향을_가진다() { + public void 차는_초나라에서_동서남북_직선_경로를_보드_끝까지_가진다() { MoveStrategy strategy = new RookMoveStrategy(); List paths = strategy.getPaths(TeamColor.CHO); - assertThat(paths).hasSize(4); - assertThat(paths).containsExactlyInAnyOrder( + assertThat(paths).hasSize(36); + assertThat(paths).contains( new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.NORTH, Direction.NORTH, Direction.NORTH, Direction.NORTH)), new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.SOUTH, Direction.SOUTH, Direction.SOUTH, Direction.SOUTH)), new MovePath(List.of(Direction.EAST)), - new MovePath(List.of(Direction.WEST)) + new MovePath(List.of(Direction.EAST, Direction.EAST, Direction.EAST, Direction.EAST)), + new MovePath(List.of(Direction.WEST)), + new MovePath(List.of(Direction.WEST, Direction.WEST, Direction.WEST, Direction.WEST)) ); } @Test - public void 차는_한나라에서_동서남북_4방향을_가진다() { + public void 차는_현재위치에서_여러칸_떨어진_직선_목적지_경로를_생성한다() { MoveStrategy strategy = new RookMoveStrategy(); - List paths = strategy.getPaths(TeamColor.HAN); + List routes = strategy.makeRoutes(Position.of(4, 4), TeamColor.HAN); - assertThat(paths).hasSize(4); - assertThat(paths).containsExactlyInAnyOrder( - new MovePath(List.of(Direction.NORTH)), - new MovePath(List.of(Direction.SOUTH)), - new MovePath(List.of(Direction.EAST)), - new MovePath(List.of(Direction.WEST)) + assertThat(routes).contains( + new Route(Position.of(4, 4), Position.of(0, 4), + List.of(Position.of(3, 4), Position.of(2, 4), Position.of(1, 4))), + new Route(Position.of(4, 4), Position.of(4, 8), + List.of(Position.of(4, 5), Position.of(4, 6), Position.of(4, 7))), + new Route(Position.of(4, 4), Position.of(4, 0), + List.of(Position.of(4, 3), Position.of(4, 2), Position.of(4, 1))) ); } } @@ -51,8 +56,8 @@ class 이동경로 { class 차단검사 { @Test public void 차는_장애물이_없으면_지나갈수_있다(){ - MoveStrategy moveStrategy = new PawnMoveStrategy(); - Route route = new Route(Position.of(4, 4), Position.of(3, 4), List.of()); + MoveStrategy moveStrategy = new RookMoveStrategy(); + Route route = new Route(Position.of(4, 4), Position.of(1, 4), List.of(Position.of(3, 4), Position.of(2, 4))); boolean canMove = moveStrategy.canMove(route, List.of(), Optional.empty(), TeamColor.CHO); @@ -61,8 +66,8 @@ class 차단검사 { @Test public void 차는_장애물이_하나라도_있으면_지나갈수_없다(){ - MoveStrategy moveStrategy = new PawnMoveStrategy(); - Route route = new Route(Position.of(4, 4), Position.of(3, 4), List.of()); + MoveStrategy moveStrategy = new RookMoveStrategy(); + Route route = new Route(Position.of(4, 4), Position.of(1, 4), List.of(Position.of(3, 4), Position.of(2, 4))); boolean canMove = moveStrategy.canMove( route, @@ -73,5 +78,20 @@ class 차단검사 { assertThat(canMove).isFalse(); } + + @Test + public void 차는_도착지에_같은팀_기물이_있으면_이동할수_없다() { + MoveStrategy moveStrategy = new RookMoveStrategy(); + Route route = new Route(Position.of(4, 4), Position.of(1, 4), List.of(Position.of(3, 4), Position.of(2, 4))); + + boolean canMove = moveStrategy.canMove( + route, + List.of(), + Optional.of(Piece.of(TeamColor.CHO, PieceType.GUARD)), + TeamColor.CHO + ); + + assertThat(canMove).isFalse(); + } } } From c62155e020a8f30438e29f2c671b691907cdc2ee Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sat, 28 Mar 2026 02:00:18 +0900 Subject: [PATCH 63/82] =?UTF-8?q?refactor:=20=ED=96=89=20=EC=97=B4=20?= =?UTF-8?q?=EC=A2=8C=ED=91=9C=20=EC=B2=B4=EA=B3=84=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/domain/Column.java | 4 +-- src/main/java/domain/Position.java | 2 +- src/main/java/domain/Row.java | 4 +-- .../formation/InitialFormationStrategy.java | 30 ++++++++-------- .../formation/InnerFormationStrategy.java | 30 ++++++---------- .../formation/LeftFormationStrategy.java | 10 +++--- .../formation/OuterFormationStrategy.java | 10 +++--- .../formation/RightFormationStrategy.java | 10 +++--- src/test/java/InitializerTest.java | 4 +-- src/test/java/domain/ColumnTest.java | 2 +- src/test/java/domain/RowTest.java | 2 +- .../InitialFormationStrategyTest.java | 36 +++++++++---------- .../formation/InnerFormationStrategyTest.java | 20 +++++------ .../formation/LeftFormationStrategyTest.java | 20 +++++------ .../formation/OuterFormationStrategyTest.java | 20 +++++------ .../formation/RightFormationStrategyTest.java | 20 +++++------ 16 files changed, 108 insertions(+), 116 deletions(-) diff --git a/src/main/java/domain/Column.java b/src/main/java/domain/Column.java index 85879eb1ce..efada677ee 100644 --- a/src/main/java/domain/Column.java +++ b/src/main/java/domain/Column.java @@ -1,7 +1,7 @@ package domain; public record Column(int value) { - private static final int COLUMN_MAX_SIZE = 9; + private static final int COLUMN_MAX_SIZE = 8; public Column { validateColumn(value); @@ -12,4 +12,4 @@ private void validateColumn(int number) { throw new IllegalArgumentException("열의 최대 값은 " + COLUMN_MAX_SIZE + "입니다."); } } -} \ No newline at end of file +} diff --git a/src/main/java/domain/Position.java b/src/main/java/domain/Position.java index 8928465ddf..02c7eaaba1 100644 --- a/src/main/java/domain/Position.java +++ b/src/main/java/domain/Position.java @@ -30,7 +30,7 @@ public int column() { } public boolean isInsideBoard() { - return row() >= 0 && row() <= 8 && column() >= 0 && column() <= 9; + return row() >= 0 && row() <= 9 && column() >= 0 && column() <= 8; } @Override diff --git a/src/main/java/domain/Row.java b/src/main/java/domain/Row.java index b5ff8730e4..f33b0a0cfa 100644 --- a/src/main/java/domain/Row.java +++ b/src/main/java/domain/Row.java @@ -1,7 +1,7 @@ package domain; public record Row(int value) { - private static final int ROW_MAX_SIZE = 8; + private static final int ROW_MAX_SIZE = 9; public Row { validateRow(value); @@ -12,4 +12,4 @@ private void validateRow(int value) { throw new IllegalArgumentException("행의 최대 값은 " + ROW_MAX_SIZE + "입니다."); } } -} \ No newline at end of file +} diff --git a/src/main/java/strategy/formation/InitialFormationStrategy.java b/src/main/java/strategy/formation/InitialFormationStrategy.java index a56a047092..b5943bf784 100644 --- a/src/main/java/strategy/formation/InitialFormationStrategy.java +++ b/src/main/java/strategy/formation/InitialFormationStrategy.java @@ -30,27 +30,27 @@ private Map placeFixedPieces(TeamColor teamColor) { return createFixedMap(teamColor, 9, 8, 7, 6); } - private Map createFixedMap(TeamColor teamColor, int backRankY, int kingY, int cannonY, int pawnY) { + private Map createFixedMap(TeamColor teamColor, int backRankRow, int kingRow, int cannonRow, int pawnRow) { Map map = new HashMap<>(); - // 1. 차 (ROOK) - 양쪽 맨 끝 (x = 0, 8) - map.put(Position.of(0, backRankY), Piece.of(teamColor, PieceType.ROOK)); - map.put(Position.of(8, backRankY), Piece.of(teamColor, PieceType.ROOK)); + // 1. 차 (ROOK) - 양쪽 맨 끝 (column = 0, 8) + map.put(Position.of(backRankRow, 0), Piece.of(teamColor, PieceType.ROOK)); + map.put(Position.of(backRankRow, 8), Piece.of(teamColor, PieceType.ROOK)); - // 2. 사 (GUARD) - 궁성 안쪽 귀 (x = 3, 5) - map.put(Position.of(3, backRankY), Piece.of(teamColor, PieceType.GUARD)); - map.put(Position.of(5, backRankY), Piece.of(teamColor, PieceType.GUARD)); + // 2. 사 (GUARD) - 궁성 안쪽 귀 (column = 3, 5) + map.put(Position.of(backRankRow, 3), Piece.of(teamColor, PieceType.GUARD)); + map.put(Position.of(backRankRow, 5), Piece.of(teamColor, PieceType.GUARD)); - // 3. 왕 (KING) - 궁성 중앙 (x = 4) - map.put(Position.of(4, kingY), Piece.of(teamColor, PieceType.KING)); + // 3. 왕 (KING) - 궁성 중앙 (column = 4) + map.put(Position.of(kingRow, 4), Piece.of(teamColor, PieceType.KING)); - // 4. 포 (CANNON) - (x = 1, 7) - map.put(Position.of(1, cannonY), Piece.of(teamColor, PieceType.CANNON)); - map.put(Position.of(7, cannonY), Piece.of(teamColor, PieceType.CANNON)); + // 4. 포 (CANNON) - (column = 1, 7) + map.put(Position.of(cannonRow, 1), Piece.of(teamColor, PieceType.CANNON)); + map.put(Position.of(cannonRow, 7), Piece.of(teamColor, PieceType.CANNON)); - // 5. 졸/병 (PAWN) - 5개 (x = 0, 2, 4, 6, 8) - for (int x = 0; x <= 8; x += 2) { - map.put(Position.of(x, pawnY), Piece.of(teamColor, PieceType.PAWN)); + // 5. 졸/병 (PAWN) - 5개 (column = 0, 2, 4, 6, 8) + for (int column = 0; column <= 8; column += 2) { + map.put(Position.of(pawnRow, column), Piece.of(teamColor, PieceType.PAWN)); } return map; diff --git a/src/main/java/strategy/formation/InnerFormationStrategy.java b/src/main/java/strategy/formation/InnerFormationStrategy.java index 4de513f819..3b6e15dfcc 100644 --- a/src/main/java/strategy/formation/InnerFormationStrategy.java +++ b/src/main/java/strategy/formation/InnerFormationStrategy.java @@ -12,28 +12,20 @@ public class InnerFormationStrategy extends InitialFormationStrategy { @Override protected Map setupFormation(TeamColor teamColor) { Map formation = new HashMap<>(); - int y; + int row; if (teamColor.equals(TeamColor.CHO)) { - y =9; - // 왼쪽 마 (x=1) - formation.put(Position.of(1, y), Piece.of(teamColor, PieceType.HORSE)); - // 왼쪽 상 (x=2) - formation.put(Position.of(2, y), Piece.of(teamColor, PieceType.ELEPHANT)); - // 오른쪽 상 (x=6) - formation.put(Position.of(6, y), Piece.of(teamColor, PieceType.ELEPHANT)); - // 오른쪽 마 (x=7) - formation.put(Position.of(7, y), Piece.of(teamColor, PieceType.HORSE)); + row = 9; + formation.put(Position.of(row, 1), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(row, 2), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(row, 6), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(row, 7), Piece.of(teamColor, PieceType.HORSE)); return formation; } - y=0; - // 왼쪽 마 (x=1) - formation.put(Position.of(1, y), Piece.of(teamColor, PieceType.HORSE)); - // 왼쪽 상 (x=2) - formation.put(Position.of(2, y), Piece.of(teamColor, PieceType.ELEPHANT)); - // 오른쪽 상 (x=6) - formation.put(Position.of(6, y), Piece.of(teamColor, PieceType.ELEPHANT)); - // 오른쪽 마 (x=7) - formation.put(Position.of(7, y), Piece.of(teamColor, PieceType.HORSE)); + row = 0; + formation.put(Position.of(row, 1), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(row, 2), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(row, 6), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(row, 7), Piece.of(teamColor, PieceType.HORSE)); return formation; } diff --git a/src/main/java/strategy/formation/LeftFormationStrategy.java b/src/main/java/strategy/formation/LeftFormationStrategy.java index 05473ba70b..7d3e5799a1 100644 --- a/src/main/java/strategy/formation/LeftFormationStrategy.java +++ b/src/main/java/strategy/formation/LeftFormationStrategy.java @@ -12,12 +12,12 @@ public class LeftFormationStrategy extends InitialFormationStrategy { @Override protected Map setupFormation(TeamColor teamColor) { Map formation = new HashMap<>(); - int y = teamColor == TeamColor.CHO ? 9 : 0; + int row = teamColor == TeamColor.CHO ? 9 : 0; - formation.put(Position.of(1, y), Piece.of(teamColor, PieceType.HORSE)); - formation.put(Position.of(2, y), Piece.of(teamColor, PieceType.ELEPHANT)); - formation.put(Position.of(6, y), Piece.of(teamColor, PieceType.HORSE)); - formation.put(Position.of(7, y), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(row, 1), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(row, 2), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(row, 6), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(row, 7), Piece.of(teamColor, PieceType.ELEPHANT)); return formation; } } diff --git a/src/main/java/strategy/formation/OuterFormationStrategy.java b/src/main/java/strategy/formation/OuterFormationStrategy.java index b718f09c73..2078528e38 100644 --- a/src/main/java/strategy/formation/OuterFormationStrategy.java +++ b/src/main/java/strategy/formation/OuterFormationStrategy.java @@ -12,12 +12,12 @@ public class OuterFormationStrategy extends InitialFormationStrategy { @Override protected Map setupFormation(TeamColor teamColor) { Map formation = new HashMap<>(); - int y = teamColor == TeamColor.CHO ? 9 : 0; + int row = teamColor == TeamColor.CHO ? 9 : 0; - formation.put(Position.of(1, y), Piece.of(teamColor, PieceType.ELEPHANT)); - formation.put(Position.of(2, y), Piece.of(teamColor, PieceType.HORSE)); - formation.put(Position.of(6, y), Piece.of(teamColor, PieceType.HORSE)); - formation.put(Position.of(7, y), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(row, 1), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(row, 2), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(row, 6), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(row, 7), Piece.of(teamColor, PieceType.ELEPHANT)); return formation; } } diff --git a/src/main/java/strategy/formation/RightFormationStrategy.java b/src/main/java/strategy/formation/RightFormationStrategy.java index 74a05ac155..f5c3ff2319 100644 --- a/src/main/java/strategy/formation/RightFormationStrategy.java +++ b/src/main/java/strategy/formation/RightFormationStrategy.java @@ -12,12 +12,12 @@ public class RightFormationStrategy extends InitialFormationStrategy { @Override protected Map setupFormation(TeamColor teamColor) { Map formation = new HashMap<>(); - int y = teamColor == TeamColor.CHO ? 9 : 0; + int row = teamColor == TeamColor.CHO ? 9 : 0; - formation.put(Position.of(1, y), Piece.of(teamColor, PieceType.ELEPHANT)); - formation.put(Position.of(2, y), Piece.of(teamColor, PieceType.HORSE)); - formation.put(Position.of(6, y), Piece.of(teamColor, PieceType.ELEPHANT)); - formation.put(Position.of(7, y), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(row, 1), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(row, 2), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(row, 6), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(row, 7), Piece.of(teamColor, PieceType.HORSE)); return formation; } } diff --git a/src/test/java/InitializerTest.java b/src/test/java/InitializerTest.java index ea306d01e3..b8fa6b8bd4 100644 --- a/src/test/java/InitializerTest.java +++ b/src/test/java/InitializerTest.java @@ -33,8 +33,8 @@ class 초기화 { @Test void 초나라_한나라_전략을_주입받아_총_32개의_기물이_세팅된_초기_장기판을_반환한다() { assertThat(initialGameState.boardState()).hasSize(32); - assertThat(initialGameState.boardState().get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); - assertThat(initialGameState.boardState().get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(initialGameState.boardState().get(Position.of(8, 4)).getPieceType()).isEqualTo(PieceType.KING); + assertThat(initialGameState.boardState().get(Position.of(0, 2)).getPieceType()).isEqualTo(PieceType.ELEPHANT); } } diff --git a/src/test/java/domain/ColumnTest.java b/src/test/java/domain/ColumnTest.java index de7269bbd9..f97ccc59b3 100644 --- a/src/test/java/domain/ColumnTest.java +++ b/src/test/java/domain/ColumnTest.java @@ -27,7 +27,7 @@ class 예외 { assertThatThrownBy(() -> new Column(input)) .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("열의 최대 값은 9입니다."); + .hasMessageContaining("열의 최대 값은 8입니다."); } } } diff --git a/src/test/java/domain/RowTest.java b/src/test/java/domain/RowTest.java index 0d1abec1d7..0b3abe2dc8 100644 --- a/src/test/java/domain/RowTest.java +++ b/src/test/java/domain/RowTest.java @@ -27,7 +27,7 @@ class 예외 { assertThatThrownBy(() -> new Row(input)) .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("행의 최대 값은 8입니다."); + .hasMessageContaining("행의 최대 값은 9입니다."); } } } diff --git a/src/test/java/strategy/formation/InitialFormationStrategyTest.java b/src/test/java/strategy/formation/InitialFormationStrategyTest.java index c51c8fabfc..ad7c8b067d 100644 --- a/src/test/java/strategy/formation/InitialFormationStrategyTest.java +++ b/src/test/java/strategy/formation/InitialFormationStrategyTest.java @@ -29,15 +29,15 @@ class 한나라 { assertThat(result).hasSize(12); assertThat(result.get(Position.of(0, 0)).getPieceType()).isEqualTo(PieceType.ROOK); - assertThat(result.get(Position.of(8, 0)).getPieceType()).isEqualTo(PieceType.ROOK); - assertThat(result.get(Position.of(3, 0)).getPieceType()).isEqualTo(PieceType.GUARD); - assertThat(result.get(Position.of(5, 0)).getPieceType()).isEqualTo(PieceType.GUARD); - assertThat(result.get(Position.of(4, 1)).getPieceType()).isEqualTo(PieceType.KING); - assertThat(result.get(Position.of(1, 2)).getPieceType()).isEqualTo(PieceType.CANNON); - assertThat(result.get(Position.of(7, 2)).getPieceType()).isEqualTo(PieceType.CANNON); - assertThat(result.get(Position.of(0, 3)).getPieceType()).isEqualTo(PieceType.PAWN); - assertThat(result.get(Position.of(4, 3)).getPieceType()).isEqualTo(PieceType.PAWN); - assertThat(result.get(Position.of(8, 3)).getPieceType()).isEqualTo(PieceType.PAWN); + assertThat(result.get(Position.of(0, 8)).getPieceType()).isEqualTo(PieceType.ROOK); + assertThat(result.get(Position.of(0, 3)).getPieceType()).isEqualTo(PieceType.GUARD); + assertThat(result.get(Position.of(0, 5)).getPieceType()).isEqualTo(PieceType.GUARD); + assertThat(result.get(Position.of(1, 4)).getPieceType()).isEqualTo(PieceType.KING); + assertThat(result.get(Position.of(2, 1)).getPieceType()).isEqualTo(PieceType.CANNON); + assertThat(result.get(Position.of(2, 7)).getPieceType()).isEqualTo(PieceType.CANNON); + assertThat(result.get(Position.of(3, 0)).getPieceType()).isEqualTo(PieceType.PAWN); + assertThat(result.get(Position.of(3, 4)).getPieceType()).isEqualTo(PieceType.PAWN); + assertThat(result.get(Position.of(3, 8)).getPieceType()).isEqualTo(PieceType.PAWN); } } @@ -48,16 +48,16 @@ class 초나라 { Map result = strategy.setUpPieces(TeamColor.CHO); assertThat(result).hasSize(12); - assertThat(result.get(Position.of(0, 9)).getPieceType()).isEqualTo(PieceType.ROOK); - assertThat(result.get(Position.of(8, 9)).getPieceType()).isEqualTo(PieceType.ROOK); - assertThat(result.get(Position.of(3, 9)).getPieceType()).isEqualTo(PieceType.GUARD); - assertThat(result.get(Position.of(5, 9)).getPieceType()).isEqualTo(PieceType.GUARD); - assertThat(result.get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); - assertThat(result.get(Position.of(1, 7)).getPieceType()).isEqualTo(PieceType.CANNON); + assertThat(result.get(Position.of(9, 0)).getPieceType()).isEqualTo(PieceType.ROOK); + assertThat(result.get(Position.of(9, 8)).getPieceType()).isEqualTo(PieceType.ROOK); + assertThat(result.get(Position.of(9, 3)).getPieceType()).isEqualTo(PieceType.GUARD); + assertThat(result.get(Position.of(9, 5)).getPieceType()).isEqualTo(PieceType.GUARD); + assertThat(result.get(Position.of(8, 4)).getPieceType()).isEqualTo(PieceType.KING); + assertThat(result.get(Position.of(7, 1)).getPieceType()).isEqualTo(PieceType.CANNON); assertThat(result.get(Position.of(7, 7)).getPieceType()).isEqualTo(PieceType.CANNON); - assertThat(result.get(Position.of(0, 6)).getPieceType()).isEqualTo(PieceType.PAWN); - assertThat(result.get(Position.of(4, 6)).getPieceType()).isEqualTo(PieceType.PAWN); - assertThat(result.get(Position.of(8, 6)).getPieceType()).isEqualTo(PieceType.PAWN); + assertThat(result.get(Position.of(6, 0)).getPieceType()).isEqualTo(PieceType.PAWN); + assertThat(result.get(Position.of(6, 4)).getPieceType()).isEqualTo(PieceType.PAWN); + assertThat(result.get(Position.of(6, 8)).getPieceType()).isEqualTo(PieceType.PAWN); } } } diff --git a/src/test/java/strategy/formation/InnerFormationStrategyTest.java b/src/test/java/strategy/formation/InnerFormationStrategyTest.java index e965b69f7f..efdb98911b 100644 --- a/src/test/java/strategy/formation/InnerFormationStrategyTest.java +++ b/src/test/java/strategy/formation/InnerFormationStrategyTest.java @@ -27,11 +27,11 @@ class 한나라 { Map formation = initialFormationStrategy.setUpPieces(TeamColor.HAN); assertThat(formation.size()).isEqualTo(16); - assertThat(formation.get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(6, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(1, 0)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(7, 0)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(4, 1)).getPieceType()).isEqualTo(PieceType.KING); + assertThat(formation.get(Position.of(0, 2)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(0, 6)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(0, 1)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(0, 7)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(1, 4)).getPieceType()).isEqualTo(PieceType.KING); } } @@ -42,11 +42,11 @@ class 초나라 { Map formation = initialFormationStrategy.setUpPieces(TeamColor.CHO); assertThat(formation.size()).isEqualTo(16); - assertThat(formation.get(Position.of(2, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(6, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(7, 9)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(1, 9)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); + assertThat(formation.get(Position.of(9, 2)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(9, 6)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(9, 7)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(9, 1)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(8, 4)).getPieceType()).isEqualTo(PieceType.KING); } } } diff --git a/src/test/java/strategy/formation/LeftFormationStrategyTest.java b/src/test/java/strategy/formation/LeftFormationStrategyTest.java index 981fab93b2..3ba865d7e6 100644 --- a/src/test/java/strategy/formation/LeftFormationStrategyTest.java +++ b/src/test/java/strategy/formation/LeftFormationStrategyTest.java @@ -27,11 +27,11 @@ class 한나라 { Map formation = initialFormationStrategy.setUpPieces(TeamColor.HAN); assertThat(formation.size()).isEqualTo(16); - assertThat(formation.get(Position.of(1, 0)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(6, 0)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(7, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(4, 1)).getPieceType()).isEqualTo(PieceType.KING); + assertThat(formation.get(Position.of(0, 1)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(0, 2)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(0, 6)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(0, 7)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(1, 4)).getPieceType()).isEqualTo(PieceType.KING); } } @@ -42,11 +42,11 @@ class 초나라 { Map formation = initialFormationStrategy.setUpPieces(TeamColor.CHO); assertThat(formation.size()).isEqualTo(16); - assertThat(formation.get(Position.of(1, 9)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(2, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(6, 9)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(7, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); + assertThat(formation.get(Position.of(9, 1)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(9, 2)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(9, 6)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(9, 7)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(8, 4)).getPieceType()).isEqualTo(PieceType.KING); } } } diff --git a/src/test/java/strategy/formation/OuterFormationStrategyTest.java b/src/test/java/strategy/formation/OuterFormationStrategyTest.java index f3fc38bb7f..fc1adc7522 100644 --- a/src/test/java/strategy/formation/OuterFormationStrategyTest.java +++ b/src/test/java/strategy/formation/OuterFormationStrategyTest.java @@ -26,11 +26,11 @@ class 한나라 { Map formation = initialFormationStrategy.setUpPieces(TeamColor.HAN); assertThat(formation.size()).isEqualTo(16); - assertThat(formation.get(Position.of(1, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(7, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(6, 0)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(4, 1)).getPieceType()).isEqualTo(PieceType.KING); + assertThat(formation.get(Position.of(0, 1)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(0, 7)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(0, 2)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(0, 6)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(1, 4)).getPieceType()).isEqualTo(PieceType.KING); } } @@ -41,11 +41,11 @@ class 초나라 { Map formation = initialFormationStrategy.setUpPieces(TeamColor.CHO); assertThat(formation.size()).isEqualTo(16); - assertThat(formation.get(Position.of(1, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(7, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(2, 9)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(6, 9)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); + assertThat(formation.get(Position.of(9, 1)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(9, 7)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(9, 2)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(9, 6)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(8, 4)).getPieceType()).isEqualTo(PieceType.KING); } } } diff --git a/src/test/java/strategy/formation/RightFormationStrategyTest.java b/src/test/java/strategy/formation/RightFormationStrategyTest.java index b4b9c28940..527f3f5e39 100644 --- a/src/test/java/strategy/formation/RightFormationStrategyTest.java +++ b/src/test/java/strategy/formation/RightFormationStrategyTest.java @@ -27,11 +27,11 @@ class 한나라 { Map formation = initialFormationStrategy.setUpPieces(TeamColor.HAN); assertThat(formation.size()).isEqualTo(16); - assertThat(formation.get(Position.of(1, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(2, 0)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(6, 0)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(7, 0)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(4, 1)).getPieceType()).isEqualTo(PieceType.KING); + assertThat(formation.get(Position.of(0, 1)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(0, 2)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(0, 6)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(0, 7)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(1, 4)).getPieceType()).isEqualTo(PieceType.KING); } } @@ -42,11 +42,11 @@ class 초나라 { Map formation = initialFormationStrategy.setUpPieces(TeamColor.CHO); assertThat(formation.size()).isEqualTo(16); - assertThat(formation.get(Position.of(1, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(2, 9)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(6, 9)).getPieceType()).isEqualTo(PieceType.ELEPHANT); - assertThat(formation.get(Position.of(7, 9)).getPieceType()).isEqualTo(PieceType.HORSE); - assertThat(formation.get(Position.of(4, 8)).getPieceType()).isEqualTo(PieceType.KING); + assertThat(formation.get(Position.of(9, 1)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(9, 2)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(9, 6)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(formation.get(Position.of(9, 7)).getPieceType()).isEqualTo(PieceType.HORSE); + assertThat(formation.get(Position.of(8, 4)).getPieceType()).isEqualTo(PieceType.KING); } } } From a968d03082b3686a73a3ff67067c3730e9320e24 Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sat, 28 Mar 2026 02:09:21 +0900 Subject: [PATCH 64/82] =?UTF-8?q?docs:=20README.md=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 151 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 79 insertions(+), 72 deletions(-) diff --git a/README.md b/README.md index 5c9f914f06..ef251ff6c2 100644 --- a/README.md +++ b/README.md @@ -42,92 +42,101 @@ - [x] [기능구현][예외처리] 장기판에서 사용할 좌표 체계를 정의 - `Position`, `Direction`, `Route`가 어떤 의미를 가지는지 먼저 확정 - - 좌표 범위, 방향 표현 방식, 경로의 시작/끝/중간 위치를 어떻게 다룰지 결정 + - 좌표 체계는 `Position.of(row, column)` 기준으로 정리 + - 행은 위에서 아래로 `0..9`, 열은 왼쪽에서 오른쪽으로 `0..8` - [예외처리] 유효하지 않은 좌표 생성 방지 -- [ ] [기능구현] 기물의 이동 규칙을 어떤 방식으로 표현할지 확정 - - 이동 규칙을 단순 방향 목록으로 표현할지, 경로(Route) 생성까지 포함할지 결정 +- [x] [기능구현] 기물의 이동 규칙을 어떤 방식으로 표현할지 확정 + - 이동 규칙을 `MovePath`와 `Route` 생성 기반으로 표현 + - 단순 방향 목록뿐 아니라 중간 경로까지 포함하도록 정리 - 궁성 영역 관련 규칙은 제외 -- [ ] [기능구현] 기물이 자신의 팀, 종류, 이동 규칙을 가지도록 공통 구조를 만든다 +- [x] [기능구현] 기물이 자신의 팀, 종류, 이동 규칙을 가지도록 공통 구조를 만든다 - 모든 기물이 공통적으로 가져야 하는 속성과 동작을 정의 + - `Piece`가 `TeamColor`, `PieceType`, `MoveStrategy`를 조합하도록 구성 -- [ ] [기능구현] 각 기물을 게임에서 사용할 수 있는 형태로 구체화 - - 상, 마, 차, 졸, 사, 왕이 각각 생성 가능하도록 - - 생성 시 팀 정보와 이동 규칙이 자연스럽게 연결되도록 +- [x] [기능구현] 각 기물을 게임에서 사용할 수 있는 형태로 구체화 + - 상, 마, 차, 졸, 사, 왕, 포가 생성 가능하도록 구현 + - 생성 시 팀 정보와 이동 규칙이 자연스럽게 연결되도록 구성 -- [ ] [상태관리][예외처리] 장기판의 현재 기물 배치 상태 저장, 조회 기능 구현 - - 특정 위치에 어떤 기물이 있는지 확인할 수 있도록 - - [예외처리] 존재하지 않는 위치 조회 방지 +- [x] [상태관리][예외처리] 장기판의 현재 기물 배치 상태 저장, 조회 기능 구현 + - `Map` 기반으로 현재 배치 상태를 저장하고 조회 + - 특정 위치의 기물 조회, 특정 기물의 현재 위치 조회 가능 + - [예외처리] 보드에 없는 기물 이동 시 예외 처리 - [x] [초기화] 게임 시작 시 장기판을 초기 상태로 세팅 - 초기 기물 생성 - 초기 배치 좌표 정의 - 초기 장기판 세팅 -- [ ] [기능구현] 규칙이 단순한 기물의 이동 가능 후보 경로를 계산 - - 비교적 단순한 기물부터 시작 ex) `졸`, `사`, `왕` +- [x] [기능구현] 규칙이 단순한 기물의 이동 가능 후보 경로를 계산 + - `졸`, `사`, `왕`의 후보 경로 계산 구현 - 궁성 영역 관련 규칙은 제외 - - 전체 흐름 빠르게 검증 -- [ ] [기능구현] 규칙이 복잡한 기물의 이동 가능 후보 경로를 계산 - - 경로와 중간 칸의 영향을 크게 받는 기물의 규칙을 구현 ex) `차`, `마`, `상` +- [x] [기능구현] 규칙이 복잡한 기물의 이동 가능 후보 경로를 계산 + - `차`, `포`, `마`, `상`의 후보 경로 계산 구현 + - 차와 포는 직선 장거리 경로를 생성하도록 구현 -- [ ] [판정] 장기판이 빈 칸 여부와 경로 차단 여부를 판단하는 기능 구현 - - 단순히 목적지만 보는 것이 아니라, 이동 경로 중간 칸도 검사할 수 있도록 +- [x] [판정] 장기판이 빈 칸 여부와 경로 차단 여부를 판단하는 기능 구현 + - 목적지 점유 여부와 이동 경로 중간 칸 차단 여부를 함께 판단 + - 포의 다리 규칙도 중간 경로 정보를 활용해 판정 -- [ ] [판정][예외처리] 기물이 선택한 목적지로 실제 이동 가능한지 판정하는 기능 구현 +- [x] [판정][예외처리] 기물이 선택한 목적지로 실제 이동 가능한지 판정하는 기능 구현 - 기물이 만든 이동 후보와 현재 장기판 상태를 함께 고려 - 아군이 있는 칸인지, 적군이 있는 칸인지, 중간 경로가 막혔는지 등을 종합적으로 판정 - 궁성 관련 판정은 제외 - [예외처리] 이동 불가능한 경우 명확히 거부 -- [ ] [기능구현][상태관리][예외처리] 장기판에 기물을 배치하고 이동하는 기능 구현 - - 초기 배치와 실제 게임 중 이동 모두 처리할 수 있도록 - - [ ] [상태관리] 이동 후 보드 상태 갱신 +- [x] [기능구현][상태관리][예외처리] 장기판에 기물을 배치하고 이동하는 기능 구현 + - 초기 배치와 실제 게임 중 이동 모두 처리할 수 있도록 구현 + - [x] [상태관리] 이동 후 보드 상태 갱신 - [예외처리] 잘못된 이동 요청(범위 밖, 규칙 위반) 방지 -- [ ] [출력] 초기 장기판 상태를 출력할 수 있도록 - - 1.1단계 초기화 결과를 눈으로 검증할 수 있어야 한다 +- [x] [출력] 초기 장기판 상태를 출력할 수 있도록 + - 초기화 결과를 콘솔 보드 형태로 확인 가능 -- [ ] [출력] 특정 기물의 이동 후보 또는 이동 결과를 확인할 수 있도록 - - 1.2단계 이동 규칙 구현 결과를 눈으로 검증할 수 있어야 한다 +- [x] [출력] 특정 기물의 이동 후보 또는 이동 결과를 확인할 수 있도록 + - 선택 가능한 기물 목록 출력 + - 선택한 기물의 이동 후보 경로 출력 + - 이동 결과 출력 + +- [x] [상태관리] `TeamColor` 기반으로 현재 턴과 진영 상태를 관리 + - 별도의 Player 객체 없이 현재 턴 팀을 기준으로 게임 흐름을 제어 + - 현재 턴 확인 및 턴 교체 구현 + +- [x] [기능구현][상태관리] 포획이 발생했을 때 게임 상태 갱신 + - 이동한 목적지에 상대 기물이 있으면 기존 기물을 덮어써 포획 처리 + - [x] [상태관리] `Map` 보드 상태를 기준으로 점유 정보를 갱신 + +- [ ] [기능구현] 현재 보드 상태를 기준으로 팀별 점수를 계산 + - 시간 초과 시 `Map`에 남아 있는 기물을 기준으로 점수를 계산 + +- [x] [게임흐름] 턴 교체 + - 현재 턴 `TeamColor` 확인 + - 다음 턴 `TeamColor` 확인 + +- [x] [게임흐름][입력][출력] 최소 플레이가 가능한 게임 루프 생성 +- [x] [출력] 현재 턴 팀의 기물 목록 출력 + - [x] [입력] 기물 선택 입력 처리 + - [x] [출력] 이동 후보 위치 출력 + - [x] [입력] 목적지 선택 입력 처리 + - [x] [기능구현] 이동 수행 + - [x] [출력] 현재 장기판 상태 출력 + - [x] [게임흐름] 턴 교체 + - 장군/외통수/시간 제한 배제하고 한 턴씩 진행 되도록 + +- [x] [입력][게임흐름][예외처리] 잘못된 입력이 들어왔을 때 같은 흐름 안에서 다시 선택할 수 있도록 + - [x] [입력] 존재하지 않는 기물 선택 + - [x] [입력] 이동 불가능한 목적지 선택 + - [x] [입력] 잘못된 형식의 입력 처리 + - [x] [예외처리] 입력 오류 발생 시 재입력 유도 + - [x] [게임흐름] 입력 오류가 났을 때 게임 전체가 깨지지 않고 현재 단계만 다시 진행되도록 --- ### 사이클2 구현 내용 -- [ ] [상태관리] `TeamColor` 기반으로 현재 턴과 진영 상태를 관리 - - 별도의 Player 객체 없이 현재 턴 팀을 기준으로 게임 흐름을 제어 - - 승패, 점수, 선택 가능 기물 판정도 팀 기준으로 확장 -- [ ] [기능구현][상태관리] 포획이 발생했을 때 게임 상태 갱신 - - 이동한 목적지에 상대 기물이 있으면 포획으로 처리 - - [ ] [상태관리] `Map` 보드 상태를 기준으로 점유 정보를 갱신 - -- [ ] [기능구현] 현재 보드 상태를 기준으로 팀별 점수를 계산 - - 시간 초과 시 `Map`에 남아 있는 기물을 기준으로 점수를 계산 - -- [ ] [게임흐름] 턴 교체 - - 현재 턴 `TeamColor` 확인 - - 다음 턴 `TeamColor` 확인 - -- [ ] [게임흐름][입력][출력] 최소 플레이가 가능한 게임 루프 생성 -- [출력] 현재 턴 팀의 기물 목록 출력 - - [입력] 기물 선택 입력 처리 - - [출력] 이동 후보 위치 출력 - - [입력] 목적지 선택 입력 처리 - - [기능구현] 이동 수행 - - [출력] 현재 장기판 상태 출력 - - [게임흐름] 턴 교체 - - 장군/외통수/시간 제한 배제하고 한턴 씩은 진행 되도록 - -- [ ] [입력][게임흐름][예외처리] 잘못된 입력이 들어왔을 때 같은 흐름 안에서 다시 선택할 수 있도록 - - [입력] 존재하지 않는 기물 선택 - - [입력] 이동 불가능한 목적지 선택 - - [입력] 잘못된 형식의 입력 처리 - - [예외처리] 입력 오류 발생 시 재입력 유도 - - [게임흐름] 입력 오류가 났을 때 게임 전체가 깨지지 않고 현재 단계만 다시 진행되도록 - [ ] [판정] 장군 멍군 구현 - 현재 보드 상태 기준으로 장군 여부를 판단 @@ -158,36 +167,35 @@ ### Position 시나리오 - 장기판 범위 내의 좌표로 생성할 시 정상 생성. - 장기판 범위 밖의 좌표로 생성할 시에는 예외 처리 +- 행(`row`)과 열(`column`) 범위를 각각 검증 ### JanggiBoard 시나리오 - 보드 상태는 `Map` 형태로 관리한다. - Initializer로부터 초기화되었을 때 모든 말들의 위치정보를 가지고 있다. -- 기물과 해당 기물의 direction규칙을 받으면, 그 기물이 이동 가능한지 여부를 반환한다. - - 범위를 초과하면 '이동'할 수 없다 - - 이동하고자 하는 곳에 다른 기물이 있으면 이동할 수 없다 +- 기물과 현재 판 상태를 기반으로 이동 가능한지 여부를 반환한다. + - 범위를 초과하면 이동할 수 없다 + - 이동하고자 하는 곳에 같은 팀 기물이 있으면 이동할 수 없다 + - 이동 경로에 다른 기물이 있으면 규칙에 맞지 않는 경우 이동할 수 없다 ### MoveStrategy 시나리오 -- 각 말들의 MoveStrategy가 우리가 의도한 규칙에 맞게 List이 생성된다. (졸은 옆으로 한 칸, 차는 상하좌우 등..) -- 같은 말 위에 같은 팀 말 안된다. +- 각 말들의 MoveStrategy가 우리가 의도한 규칙에 맞게 `MovePath`를 생성한다. + - 졸은 전진과 좌우 한 칸 + - 차는 상하좌우 장거리 + - 포는 상하좌우 장거리 + 다리 규칙 +- 같은 팀 말이 있는 도착지로는 이동할 수 없다. - 상 - 마 - 차 - 졸 - - 포: intermediateRoutes에서 가져온 말들의 개수가 1이고, 포가 아닌 경우 + - 포: intermediateRoutes에서 가져온 말들의 개수가 1이고, 포가 아닌 경우만 이동 가능 - 사 - 왕 -- 장기 보드와 협력하여 이동 가능한 위치 정보를 받아 루트 정보들을 생성한다. (단, 경로가 막히는 경우는 고려하지 않는다.) +- 장기 보드와 협력하여 이동 가능한 위치 정보를 받아 루트 정보들을 생성한다. ### Initializer 시나리오 - 게임 초기의 말들의 위치 정보를 `Map` 형태로 가지고 있다. -- - -```Java -record PieceStartPosition { - // Position(x,y) 형태로 각 말들의 초기정보를 보관 -} -``` +- `Position(row, column)` 기준으로 초/한의 초기 배치를 올바르게 구성한다. ### TurnManager 시나리오 - 현재 턴의 `TeamColor`가 무엇인지 반환한다. @@ -197,12 +205,11 @@ record PieceStartPosition { ### Runner 시나리오 - 기물 선택, 이동 위치 선택 입/출력을 진행한다. -- GameStateEnum을 기준으로 게임을 상태에 따라 실행한다. -- Intializer에게 `Map` 기반 장기판을 세팅하는 함수를 호출한다. +- Initializer에게 `Map` 기반 장기판을 세팅하는 함수를 호출한다. - 현재 턴 팀이 정상적인 기물을 선택하고, 정상적인 이동 목적지를 입력하면 보드 상태를 갱신한다. - TurnManager에게 턴을 교체하는 함수를 호출한다. - 현재 턴 팀이 정상적인 기물 번호를 선택하지 않으면, 예외를 발생하고 기물 선택으로 돌아온다. -- 현재 턴 팀이 정상적인 이동 목적지를 입력하지 않으면, 예외를 발생하고 이동 목적지 입력으로 돌아온다. +- 현재 턴 팀이 정상적인 이동 목적지를 입력하지 않으면, 예외를 발생하고 현재 턴 흐름 안에서 다시 선택한다. From bb529b82d6d9024ed995d23276ce9d643aec06a9 Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sat, 28 Mar 2026 02:39:26 +0900 Subject: [PATCH 65/82] =?UTF-8?q?docs:=20=EB=AF=B8=EC=85=98=20=EC=A4=91=20?= =?UTF-8?q?=EA=B8=B0=EB=A1=9D=20=EB=82=B4=EC=9A=A9=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/cycle1_mission_record.md | 262 ++++++++++++++++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 docs/cycle1_mission_record.md diff --git a/docs/cycle1_mission_record.md b/docs/cycle1_mission_record.md new file mode 100644 index 0000000000..b9fd9db760 --- /dev/null +++ b/docs/cycle1_mission_record.md @@ -0,0 +1,262 @@ +# Cycle1 Mission Record + +현재 코드 기준으로 사이클1 미션 기록 항목을 정리했다. 각 항목은 실제 구현 코드 일부를 스니펫으로 인용해 근거를 남겼다. + +## 1. 상태 위치를 결정할 때 고민한 순간 1회 + +규칙에 따른 말의 이동을 구현하기 위해서는 "현재 위치에서 말의 규칙을 따라 어디까지 갈 수 있는가"를 다룰 객체 `Route`가 필요했다. 이 고민은 `MoveStrategy.makeRoutes()`에 담겨있다. + +단순히 방향만 나열하는 것이 아니라 다음 세 가지를 함께 다뤄야 했다. + +- 현재 위치에서 한 단계씩 좌표를 진행할 것 +- 중간 경로를 별도로 모을 것(장애물 여부에 따라 이동 가능성 체크) +- 보드 범위를 벗어나는 경로는 버릴 것 + +이 고민의 결과가 아래 코드다. + +```java +default List makeRoutes(Position curPos, TeamColor teamColor) { + List validRoutes = new ArrayList<>(); + List paths = getPaths(teamColor); + + for (MovePath path : paths) { + List steps = path.steps(); + Position currentPos = curPos; + List intermediates = new ArrayList<>(); + + for (int i = 0; i < steps.size(); i++) { + try { + currentPos = currentPos.next(steps.get(i)); + } catch (IllegalArgumentException exception) { + currentPos = null; + break; + } + + if (i < steps.size() - 1) { + intermediates.add(currentPos); + } + } + if (currentPos == null) { + continue; + } + validRoutes.add(new Route(curPos, currentPos, intermediates)); + } + + return validRoutes; +} +``` + +여기서는 "좌표 하나"가 아니라 "시작점, 도착점, 중간 경로"를 모두 가진 `Route`를 만들도록 설계를 밀어 올린 점이 중요했다. + +## 2. 불변/캡슐화를 적용한 코드 1곳 + +불변과 캡슐화를 적용하기 위한 기준은 + +> 객체가 어떤 동작을 수행하기보다 값을 표현하는 역할이라면 불변 객체로 설계한다. + +였다. 이 기준을 현재 코드에서 가장 잘 보여주는 예시는 `MovePath`, `Route`, `Row`, `Column`이다. + +### record로 만든 값 객체 + +```java +public record MovePath(List steps) {} +``` + +```java +public record Route(Position startPos, Position endPos, List intermeidateNodes) {} +``` + +`MovePath`와 `Route`는 "이동 규칙을 설명하는 값"이지, '스스로 상태를 변경하며 행동하는 객체'가 아니다. 그래서 `record`로 두고 setter 없이 불변 값처럼 사용했다. + +Position도 record로 두고 필요한 메서드는 추가로 구현하면 되지 않을까 생각했으나, 공식 문서를 기반으로 "데이터만 담는 클래스"를 간결하게 만들기 위한 문법이라는 것을 확인하고 도메인 규칙을 알고 행동(보드 크기에 맞는 값으로 검증)해야 하는 Position은 클래스로 유지했다. + + +```java +public class Position { + private final Row row; + private final Column column; + + private Position(Row row, Column column) { + this.row = row; + this.column = column; + } + + public static Position of(int row, int column) { + return new Position(new Row(row), new Column(column)); + } +} +``` + +`Position`도 내부 필드를 `final`로 두고, 직접 원시값을 받지 않고 `Row`, `Column`을 조합해서 생성한다는 점에서 값 객체 성격을 유지하고 있다. + +## 3. 규칙 적용으로 변경한 설계 1곳 + +이번 미션에서 적용한 규칙 중 하나는 + +### 불변 객체 기준 + +- **If:** 객체가 어떤 동작을 수행하기보다 ‘값’을 표현하는 역할이라면 + → **Then:** 해당 객체는 불변 객체로 설계한다. +- 기준 + - 생성 이후 상태가 변경되지 않아야 한다. + - setter를 제공하지 않는다. + - 모든 필드는 final로 선언하는 것을 기본으로 한다. + +이 규칙을 적용하면서 `MovePath`, `Route`, `Row`, `Column`을 record/불변 객체로 유지하는 방향으로 설계를 잡았다. + +특히 `Route`를 mutable 객체로 두고 이동 중간에 값을 채워 넣는 대신, 경로 계산이 끝났을 때 완성된 값으로 한 번에 생성했다. + +```java +validRoutes.add(new Route(curPos, currentPos, intermediates)); +``` + +이렇게 해두면 경로 판정 로직이 `Route`를 수정하지 않고 읽기만 하면 되어서, 이후 `Board`, `MoveStrategy`, `Piece` 협력에서도 데이터 흐름이 단순해진다. + +## 4. 조건문을 다형성으로 대체한 코드 1곳 + +가장 대표적인 부분은 `MoveStrategy` 구조다. 기물별 이동 규칙을 `if-else`로 한 클래스에 몰아넣지 않고, 전략 객체로 분리했다. + +`Piece`는 실제 이동 계산을 직접 하지 않고 `moveStrategy`에 위임한다. + +```java +public class Piece { + private final TeamColor teamColor; + private final PieceType pieceType; + private final MoveStrategy moveStrategy; + + public List makeRoutes(Position from) { + return moveStrategy.makeRoutes(from, teamColor); + } + + public boolean canMove(Route route, List blockingPieces, Optional destinationPiece) { + return moveStrategy.canMove(route, blockingPieces, destinationPiece, teamColor); + } +} +``` + +기물별 규칙은 각 전략 클래스가 담당한다. + +```java +public class PawnMoveStrategy implements MoveStrategy { + @Override + public List getPaths(TeamColor teamColor) { + if (teamColor == TeamColor.CHO) { + return List.of( + new MovePath(List.of(Direction.NORTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)) + ); + } + + return List.of( + new MovePath(List.of(Direction.SOUTH)), + new MovePath(List.of(Direction.EAST)), + new MovePath(List.of(Direction.WEST)) + ); + } +} +``` + +```java +public class RookMoveStrategy implements MoveStrategy { + @Override + public List getPaths(TeamColor teamColor) { + List paths = new ArrayList<>(); + addStraightPaths(paths, Direction.NORTH); + addStraightPaths(paths, Direction.SOUTH); + addStraightPaths(paths, Direction.EAST); + addStraightPaths(paths, Direction.WEST); + return paths; + } +} +``` + +아직 `Piece.createMoveStrategy()` 내부에는 `PieceType`에 따른 조건문이 남아 있다. 다만 핵심 이동 규칙 자체는 `MoveStrategy` 다형성으로 분리되어 있고, 실제 행동 차이는 각 구현체가 맡고 있다는 점에서 "한 곳에서 모든 규칙을 조건문으로 처리하던 구조"보다는 훨씬 나아졌다. + +## 5. 인터페이스/추상클래스를 도입한 이유 + +### MoveStrategy 인터페이스를 도입한 이유 + +기물마다 이동 방식은 다르지만, 외부에서 볼 때 공통적인 동작이 존재했다. + +- 이동 경로를 만든다. +- 현재 보드 상태를 기준으로 실제 이동 가능 여부를 판단한다. + +이 공통으로 이루어지는 동작을 `MoveStrategy` 인터페이스로 추상화 했다. + +```java +public interface MoveStrategy { + + List getPaths(TeamColor teamColor); + + default List makeRoutes(Position curPos, TeamColor teamColor) { ... } + + default boolean canMove(Route route, List blockingPieces, Optional destinationPiece, TeamColor myTeam) { + if (!blockingPieces.isEmpty()) { + return false; + } + + return destinationPiece.isEmpty() || destinationPiece.get().getTeamColor() != myTeam; + } +} +``` + +이렇게 해두면 `Piece`는 "이 말이 졸인지 차인지"를 몰라도 된다. 그냥 `moveStrategy.makeRoutes(...)`, `moveStrategy.canMove(...)`만 호출하면 된다. + +여기서 기물 종류가 늘어나더라도 `Piece`가 협력하는 방식은 유지할 수 있다. + +### InitialFormationStrategy 추상클래스를 도입한 이유 + +상차림 선택지마다 달라지는 것은 상,마의 배치 뿐이고, 이 두 기물을 제외하고 공통으로 고정되는 배치는 같았다. + +이 공통 부분을 추상클래스로 끌어올렸다. + +```java +public abstract class InitialFormationStrategy { + + public final Map setUpPieces(TeamColor teamColor) { + Map formationPieces = setupFormation(teamColor); + Map fixedPieces = placeFixedPieces(teamColor); + Map allPieces = new HashMap<>(); + + allPieces.putAll(formationPieces); + allPieces.putAll(fixedPieces); + + return allPieces; + } + + protected abstract Map setupFormation(TeamColor teamColor); +} +``` + +그리고 실제 차이는 하위 클래스에서만 구현하도록 했다. + +```java +public class InnerFormationStrategy extends InitialFormationStrategy { + @Override + protected Map setupFormation(TeamColor teamColor) { + Map formation = new HashMap<>(); + int row; + if (teamColor.equals(TeamColor.CHO)) { + row = 9; + formation.put(Position.of(row, 1), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(row, 2), Piece.of(teamColor, PieceType.ELEPHANT)); + ... + } + ... + return formation; + } +} +``` + +"공통 초기화 절차"를 고정하고, 전략별 차이만 하위 클래스에 위임하도록 추상 클래스를 도입하였다고 할 수 있다. + +## 6. 새 기물 추가 시 변경 범위 테스트(가상) + +현재 `PieceType`에 새로운 기물을 하나 추가한다고 가정하면, 지금 구조에서는 변경 범위가 크지 않다. + +우선 새 `PieceType` 값을 추가하고, 해당 기물의 이동 규칙을 담을 `MoveStrategy` 구현체를 만든다. 그 다음 `Piece.createMoveStrategy()`에만 전략 연결을 추가하면 `Piece -> MoveStrategy -> Route` 흐름 안으로 기능을 구현할 수 있다. + +초기 배치에 포함해야 한다면 `InitialFormationStrategy` 계열에서 좌표만 추가하면 되고, 테스트는 "경로 생성 테스트", "차단/포획 판정 테스트", "초기 배치 테스트" 에 새 기물에 대한 케이스를 추가하면 된다. + +지금 구조에서는 새 기물 추가 시 수정 지점이 완전히 없지는 않지만, "이동 규칙", "전략 연결", "초기 배치", "테스트"로 범위를 예측 가능하다. \ No newline at end of file From 38e8fb4a7479f94f75924cf4d4539ef11e9e4e37 Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sat, 28 Mar 2026 14:40:45 +0900 Subject: [PATCH 66/82] =?UTF-8?q?refactor:=20=EA=B5=AC=EC=A1=B0=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=EC=97=90=20=EC=9D=98=ED=95=B4=20=EC=93=B0?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=95=8A=EB=8A=94=20InitialGameState=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/Initializer.java | 16 ++------ src/main/java/Runner.java | 4 +- src/main/java/domain/InitialGameState.java | 10 ----- src/test/java/InitializerTest.java | 43 +++++++++++----------- 4 files changed, 26 insertions(+), 47 deletions(-) delete mode 100644 src/main/java/domain/InitialGameState.java diff --git a/src/main/java/Initializer.java b/src/main/java/Initializer.java index 1aee87a40f..09fec35ed0 100644 --- a/src/main/java/Initializer.java +++ b/src/main/java/Initializer.java @@ -1,9 +1,8 @@ -import domain.InitialGameState; +import domain.Board; import domain.Piece; import domain.Position; import domain.TeamColor; import java.util.HashMap; -import java.util.List; import java.util.Map; import strategy.formation.InitialFormationStrategy; @@ -17,19 +16,10 @@ public Initializer(InitialFormationStrategy choStrategy, InitialFormationStrateg this.hanStrategy = hanStrategy; } - public InitialGameState initialize() { + public Board initialize() { Map board = new HashMap<>(); board.putAll(choStrategy.setUpPieces(TeamColor.CHO)); board.putAll(hanStrategy.setUpPieces(TeamColor.HAN)); - - List choPieces = board.values().stream() - .filter(piece -> piece.getTeamColor() == TeamColor.CHO) - .toList(); - - List hanPieces = board.values().stream() - .filter(piece -> piece.getTeamColor() == TeamColor.HAN) - .toList(); - - return new InitialGameState(board, choPieces, hanPieces); + return new Board(board); } } diff --git a/src/main/java/Runner.java b/src/main/java/Runner.java index 46d445083c..4b01300e4b 100644 --- a/src/main/java/Runner.java +++ b/src/main/java/Runner.java @@ -1,5 +1,4 @@ import domain.Board; -import domain.InitialGameState; import domain.Piece; import domain.Position; import domain.TeamColor; @@ -37,8 +36,7 @@ public void run() { InitialFormationStrategy hanStrategy = chooseFormationStrategy(TeamColor.HAN); Initializer initializer = new Initializer(choStrategy, hanStrategy); - InitialGameState initialGameState = initializer.initialize(); - Board board = new Board(initialGameState.boardState()); + Board board = initializer.initialize(); outputView.printBoard(board); diff --git a/src/main/java/domain/InitialGameState.java b/src/main/java/domain/InitialGameState.java deleted file mode 100644 index 7451ebe623..0000000000 --- a/src/main/java/domain/InitialGameState.java +++ /dev/null @@ -1,10 +0,0 @@ -package domain; - -import java.util.List; -import java.util.Map; - -public record InitialGameState( - Map boardState, - List choPieces, - List hanPieces -) {} diff --git a/src/test/java/InitializerTest.java b/src/test/java/InitializerTest.java index b8fa6b8bd4..f69d38bb78 100644 --- a/src/test/java/InitializerTest.java +++ b/src/test/java/InitializerTest.java @@ -1,4 +1,4 @@ -import domain.InitialGameState; +import domain.Board; import domain.PieceType; import domain.Position; @@ -17,14 +17,14 @@ class InitializerTest { InitialFormationStrategy choStrategy; InitialFormationStrategy hanStrategy; - InitialGameState initialGameState; + Board board; @BeforeEach public void setUp(){ choStrategy = new InnerFormationStrategy(); hanStrategy = new InnerFormationStrategy(); Initializer initializer = new Initializer(choStrategy, hanStrategy); - initialGameState = initializer.initialize(); + board = initializer.initialize(); } @@ -32,9 +32,10 @@ public void setUp(){ class 초기화 { @Test void 초나라_한나라_전략을_주입받아_총_32개의_기물이_세팅된_초기_장기판을_반환한다() { - assertThat(initialGameState.boardState()).hasSize(32); - assertThat(initialGameState.boardState().get(Position.of(8, 4)).getPieceType()).isEqualTo(PieceType.KING); - assertThat(initialGameState.boardState().get(Position.of(0, 2)).getPieceType()).isEqualTo(PieceType.ELEPHANT); + assertThat(board.findPiecesByTeam(TeamColor.CHO)).hasSize(16); + assertThat(board.findPiecesByTeam(TeamColor.HAN)).hasSize(16); + assertThat(board.findPiece(Position.of(8, 4))).get().extracting("pieceType").isEqualTo(PieceType.KING); + assertThat(board.findPiece(Position.of(0, 2))).get().extracting("pieceType").isEqualTo(PieceType.ELEPHANT); } } @@ -42,46 +43,46 @@ class 초기화 { class 기물목록 { @Test void 초나라_기물_리스트를_생성한다() { - assertThat(initialGameState.choPieces()).hasSize(16); + assertThat(board.findPiecesByTeam(TeamColor.CHO)).hasSize(16); assertThat( - initialGameState.choPieces().stream() - .filter(p -> p.getTeamColor() == TeamColor.CHO) + board.findPiecesByTeam(TeamColor.CHO).stream() + .map(entry -> entry.getValue()) .filter(p -> p.getPieceType() == PieceType.ELEPHANT) ).hasSize(2); assertThat( - initialGameState.choPieces().stream() - .filter(p -> p.getTeamColor() == TeamColor.CHO) + board.findPiecesByTeam(TeamColor.CHO).stream() + .map(entry -> entry.getValue()) .filter(p -> p.getPieceType() == PieceType.HORSE) ).hasSize(2); assertThat( - initialGameState.choPieces().stream() - .filter(p -> p.getTeamColor() == TeamColor.CHO) + board.findPiecesByTeam(TeamColor.CHO).stream() + .map(entry -> entry.getValue()) .filter(p -> p.getPieceType() == PieceType.CANNON) ).hasSize(2); assertThat( - initialGameState.choPieces().stream() - .filter(p -> p.getTeamColor() == TeamColor.CHO) + board.findPiecesByTeam(TeamColor.CHO).stream() + .map(entry -> entry.getValue()) .filter(p -> p.getPieceType() == PieceType.ROOK) ).hasSize(2); assertThat( - initialGameState.choPieces().stream() - .filter(p -> p.getTeamColor() == TeamColor.CHO) + board.findPiecesByTeam(TeamColor.CHO).stream() + .map(entry -> entry.getValue()) .filter(p -> p.getPieceType() == PieceType.GUARD) ).hasSize(2); assertThat( - initialGameState.choPieces().stream() - .filter(p -> p.getTeamColor() == TeamColor.CHO) + board.findPiecesByTeam(TeamColor.CHO).stream() + .map(entry -> entry.getValue()) .filter(p -> p.getPieceType() == PieceType.PAWN) ).hasSize(5); assertThat( - initialGameState.choPieces().stream() - .filter(p -> p.getTeamColor() == TeamColor.CHO) + board.findPiecesByTeam(TeamColor.CHO).stream() + .map(entry -> entry.getValue()) .filter(p -> p.getPieceType() == PieceType.KING) ).hasSize(1); } From 78828b3f9be17d2e16e846511e02e05f84594652 Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sat, 28 Mar 2026 14:44:01 +0900 Subject: [PATCH 67/82] =?UTF-8?q?refactor:=20Runner=20=EC=9E=85=EB=A0=A5?= =?UTF-8?q?=20=ED=9D=90=EB=A6=84=20=EB=A9=94=EC=84=9C=EB=93=9C=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/Runner.java | 81 ++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 31 deletions(-) diff --git a/src/main/java/Runner.java b/src/main/java/Runner.java index 4b01300e4b..cf444c9e9b 100644 --- a/src/main/java/Runner.java +++ b/src/main/java/Runner.java @@ -1,12 +1,14 @@ import domain.Board; import domain.Piece; import domain.Position; +import domain.Route; import domain.TeamColor; import domain.TurnManager; import io.InputView; import io.OutputView; import java.util.List; import java.util.Map; +import java.util.Optional; import strategy.formation.InitialFormationStrategy; import strategy.formation.InnerFormationStrategy; import strategy.formation.LeftFormationStrategy; @@ -49,20 +51,7 @@ private InitialFormationStrategy chooseFormationStrategy(TeamColor teamColor) { while (true) { outputView.printFormationSelectionPrompt(teamColor); try { - int choice = inputView.readFormationChoice(teamColor); - if (choice == 1) { - return new InnerFormationStrategy(); - } - if (choice == 2) { - return new OuterFormationStrategy(); - } - if (choice == 3) { - return new LeftFormationStrategy(); - } - if (choice == 4) { - return new RightFormationStrategy(); - } - throw new IllegalArgumentException("상차림 번호는 1~4 사이여야 합니다."); + return createFormationStrategy(inputView.readFormationChoice(teamColor)); } catch (RuntimeException exception) { outputView.printError("상차림 입력이 올바르지 않습니다."); } @@ -76,25 +65,13 @@ private void playTurn(Board board) { while (true) { try { - List> pieces = board.findPiecesByTeam(currentTurn); - outputView.printPieceOptions(pieces); - - int pieceChoice = inputView.readPieceChoice(currentTurn); - Piece selectedPiece = getSelectedPiece(pieces, pieceChoice); - - List routes = board.findMovableRoutes(selectedPiece); - if (routes.isEmpty()) { - throw new IllegalArgumentException("선택한 기물은 이동 가능한 경로가 없습니다."); - } - - outputView.printRouteOptions(routes); - int routeChoice = inputView.readRouteChoice(); - - if (routeChoice == 0) { + Piece selectedPiece = choosePiece(board, currentTurn); + Optional selectedRoute = chooseRoute(board, selectedPiece); + if (selectedRoute.isEmpty()) { continue; } - Position destination = getSelectedRoute(routes, routeChoice).endPos(); + Position destination = selectedRoute.get().endPos(); board.move(selectedPiece, destination); outputView.printMoveResult(selectedPiece, destination); turnManager.progressTurn(); @@ -105,6 +82,48 @@ private void playTurn(Board board) { } } + private InitialFormationStrategy createFormationStrategy(int choice) { + if (choice == 1) { + return new InnerFormationStrategy(); + } + if (choice == 2) { + return new OuterFormationStrategy(); + } + if (choice == 3) { + return new LeftFormationStrategy(); + } + if (choice == 4) { + return new RightFormationStrategy(); + } + throw new IllegalArgumentException("상차림 번호는 1~4 사이여야 합니다."); + } + + private Piece choosePiece(Board board, TeamColor currentTurn) { + List> pieces = board.findPiecesByTeam(currentTurn); + outputView.printPieceOptions(pieces); + + int pieceChoice = inputView.readPieceChoice(currentTurn); + return getSelectedPiece(pieces, pieceChoice); + } + + private Optional chooseRoute(Board board, Piece selectedPiece) { + List routes = board.findMovableRoutes(selectedPiece); + validateMovableRoutes(routes); + outputView.printRouteOptions(routes); + + int routeChoice = inputView.readRouteChoice(); + if (routeChoice == 0) { + return Optional.empty(); + } + return Optional.of(getSelectedRoute(routes, routeChoice)); + } + + private void validateMovableRoutes(List routes) { + if (routes.isEmpty()) { + throw new IllegalArgumentException("선택한 기물은 이동 가능한 경로가 없습니다."); + } + } + private Piece getSelectedPiece(List> pieces, int pieceChoice) { if (pieceChoice < 1 || pieceChoice > pieces.size()) { throw new IllegalArgumentException("기물 번호가 범위를 벗어났습니다."); @@ -112,7 +131,7 @@ private Piece getSelectedPiece(List> pieces, int piec return pieces.get(pieceChoice - 1).getValue(); } - private domain.Route getSelectedRoute(List routes, int routeChoice) { + private Route getSelectedRoute(List routes, int routeChoice) { if (routeChoice < 1 || routeChoice > routes.size()) { throw new IllegalArgumentException("경로 번호가 범위를 벗어났습니다."); } From 04b4635dfb5f6105f58ac17677f1c801e5774981 Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sat, 28 Mar 2026 14:46:11 +0900 Subject: [PATCH 68/82] =?UTF-8?q?refactor:=20MoveStrategy=20=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=20=EC=83=9D=EC=84=B1=20=EC=B1=85=EC=9E=84=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/strategy/move/MoveStrategy.java | 51 +++++++++++-------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/src/main/java/strategy/move/MoveStrategy.java b/src/main/java/strategy/move/MoveStrategy.java index 543427774b..8a7d72f8c5 100644 --- a/src/main/java/strategy/move/MoveStrategy.java +++ b/src/main/java/strategy/move/MoveStrategy.java @@ -19,30 +19,41 @@ default List makeRoutes(Position curPos, TeamColor teamColor) { List paths = getPaths(teamColor); for (MovePath path : paths) { - List steps = path.steps(); - Position currentPos = curPos; - List intermediates = new ArrayList<>(); - - - for (int i = 0; i < steps.size(); i++) { - try { - currentPos = currentPos.next(steps.get(i)); - } catch (IllegalArgumentException exception) { - currentPos = null; - break; - } - - if (i < steps.size() - 1) { - intermediates.add(currentPos); - } + createRoute(curPos, path.steps()).ifPresent(validRoutes::add); + } + + return validRoutes; + } + + private Optional createRoute(Position startPos, List steps) { + Position currentPos = startPos; + List intermediates = new ArrayList<>(); + + for (int index = 0; index < steps.size(); index++) { + Optional nextPosition = findNextPosition(currentPos, steps.get(index)); + if (nextPosition.isEmpty()) { + return Optional.empty(); } - if (currentPos == null) { - continue; + currentPos = nextPosition.get(); + + if (isIntermediateStep(index, steps.size())) { + intermediates.add(currentPos); } - validRoutes.add(new Route(curPos, currentPos, intermediates)); } - return validRoutes; + return Optional.of(new Route(startPos, currentPos, intermediates)); + } + + private Optional findNextPosition(Position currentPos, Direction direction) { + try { + return Optional.of(currentPos.next(direction)); + } catch (IllegalArgumentException exception) { + return Optional.empty(); + } + } + + private boolean isIntermediateStep(int stepIndex, int totalSteps) { + return stepIndex < totalSteps - 1; } default boolean canMove(Route route, List blockingPieces, Optional destinationPiece, TeamColor myTeam) { From c11552d534fff1b64b80425420252cbc767f1a3c Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sat, 28 Mar 2026 14:51:50 +0900 Subject: [PATCH 69/82] =?UTF-8?q?refactor:=20=EC=A0=84=EB=9E=B5=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=20=EB=B6=84=EA=B8=B0=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EB=B0=A9=EC=8B=9D=EC=9C=BC=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/Runner.java | 34 ++++++++++++++++++---------- src/main/java/domain/Piece.java | 39 ++++++++++++++++----------------- 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/src/main/java/Runner.java b/src/main/java/Runner.java index cf444c9e9b..9ad99684f6 100644 --- a/src/main/java/Runner.java +++ b/src/main/java/Runner.java @@ -6,6 +6,7 @@ import domain.TurnManager; import io.InputView; import io.OutputView; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Optional; @@ -16,6 +17,7 @@ import strategy.formation.RightFormationStrategy; public class Runner { + private static final List FORMATION_FACTORIES = createFormationFactories(); private final InputView inputView; private final OutputView outputView; @@ -83,17 +85,13 @@ private void playTurn(Board board) { } private InitialFormationStrategy createFormationStrategy(int choice) { - if (choice == 1) { - return new InnerFormationStrategy(); - } - if (choice == 2) { - return new OuterFormationStrategy(); - } - if (choice == 3) { - return new LeftFormationStrategy(); - } - if (choice == 4) { - return new RightFormationStrategy(); + validateFormationChoice(choice); + return FORMATION_FACTORIES.get(choice - 1).create(); + } + + private void validateFormationChoice(int choice) { + if (choice >= 1 && choice <= FORMATION_FACTORIES.size()) { + return; } throw new IllegalArgumentException("상차림 번호는 1~4 사이여야 합니다."); } @@ -137,4 +135,18 @@ private Route getSelectedRoute(List routes, int routeChoice) { } return routes.get(routeChoice - 1); } + + private static List createFormationFactories() { + List formationFactories = new ArrayList<>(); + formationFactories.add(InnerFormationStrategy::new); + formationFactories.add(OuterFormationStrategy::new); + formationFactories.add(LeftFormationStrategy::new); + formationFactories.add(RightFormationStrategy::new); + return List.copyOf(formationFactories); + } + + @FunctionalInterface + private interface FormationFactory { + InitialFormationStrategy create(); + } } diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/Piece.java index bb00aa25a3..f6e68fb2ac 100644 --- a/src/main/java/domain/Piece.java +++ b/src/main/java/domain/Piece.java @@ -1,6 +1,8 @@ package domain; +import java.util.EnumMap; import java.util.List; +import java.util.Map; import java.util.Optional; import strategy.move.CannonMoveStrategy; import strategy.move.ElephantMoveStrategy; @@ -12,6 +14,8 @@ import strategy.move.RookMoveStrategy; public class Piece { + private static final Map MOVE_STRATEGIES = createMoveStrategies(); + private final TeamColor teamColor; private final PieceType pieceType; private final MoveStrategy moveStrategy; @@ -43,27 +47,22 @@ public static Piece of(TeamColor teamColor, PieceType pieceType) { } private static MoveStrategy createMoveStrategy(PieceType pieceType) { - if (pieceType == PieceType.CANNON) { - return new CannonMoveStrategy(); - } - if (pieceType == PieceType.ELEPHANT) { - return new ElephantMoveStrategy(); - } - if (pieceType == PieceType.GUARD) { - return new GuardMoveStrategy(); - } - if (pieceType == PieceType.HORSE) { - return new HorseMoveStrategy(); - } - if (pieceType == PieceType.KING) { - return new KingMoveStrategy(); - } - if (pieceType == PieceType.PAWN) { - return new PawnMoveStrategy(); - } - if (pieceType == PieceType.ROOK) { - return new RookMoveStrategy(); + MoveStrategy moveStrategy = MOVE_STRATEGIES.get(pieceType); + if (moveStrategy != null) { + return moveStrategy; } throw new IllegalArgumentException("지원하지 않는 기물 타입입니다."); } + + private static Map createMoveStrategies() { + Map moveStrategies = new EnumMap<>(PieceType.class); + moveStrategies.put(PieceType.CANNON, new CannonMoveStrategy()); + moveStrategies.put(PieceType.ELEPHANT, new ElephantMoveStrategy()); + moveStrategies.put(PieceType.GUARD, new GuardMoveStrategy()); + moveStrategies.put(PieceType.HORSE, new HorseMoveStrategy()); + moveStrategies.put(PieceType.KING, new KingMoveStrategy()); + moveStrategies.put(PieceType.PAWN, new PawnMoveStrategy()); + moveStrategies.put(PieceType.ROOK, new RookMoveStrategy()); + return moveStrategies; + } } From be63431342593fed0d22728c6a109fdd43adc690 Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sat, 28 Mar 2026 14:54:48 +0900 Subject: [PATCH 70/82] =?UTF-8?q?refactor:=20Runner=20=EC=A0=84=EB=9E=B5?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20=EB=B0=A9=EC=8B=9D=20=EB=8B=A8=EC=88=9C?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Runner.java | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/src/main/java/Runner.java b/src/main/java/Runner.java index 9ad99684f6..8fc6d7ead1 100644 --- a/src/main/java/Runner.java +++ b/src/main/java/Runner.java @@ -6,7 +6,6 @@ import domain.TurnManager; import io.InputView; import io.OutputView; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Optional; @@ -17,7 +16,12 @@ import strategy.formation.RightFormationStrategy; public class Runner { - private static final List FORMATION_FACTORIES = createFormationFactories(); + private static final List FORMATIONS = List.of( + new InnerFormationStrategy(), + new OuterFormationStrategy(), + new LeftFormationStrategy(), + new RightFormationStrategy() + ); private final InputView inputView; private final OutputView outputView; @@ -86,11 +90,11 @@ private void playTurn(Board board) { private InitialFormationStrategy createFormationStrategy(int choice) { validateFormationChoice(choice); - return FORMATION_FACTORIES.get(choice - 1).create(); + return FORMATIONS.get(choice - 1); } private void validateFormationChoice(int choice) { - if (choice >= 1 && choice <= FORMATION_FACTORIES.size()) { + if (choice >= 1 && choice <= FORMATIONS.size()) { return; } throw new IllegalArgumentException("상차림 번호는 1~4 사이여야 합니다."); @@ -135,18 +139,4 @@ private Route getSelectedRoute(List routes, int routeChoice) { } return routes.get(routeChoice - 1); } - - private static List createFormationFactories() { - List formationFactories = new ArrayList<>(); - formationFactories.add(InnerFormationStrategy::new); - formationFactories.add(OuterFormationStrategy::new); - formationFactories.add(LeftFormationStrategy::new); - formationFactories.add(RightFormationStrategy::new); - return List.copyOf(formationFactories); - } - - @FunctionalInterface - private interface FormationFactory { - InitialFormationStrategy create(); - } } From 44f11f1049c0e56b4a372fbda150492d20ed78a4 Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sat, 28 Mar 2026 15:07:43 +0900 Subject: [PATCH 71/82] =?UTF-8?q?docs:=20gitignore=20=ED=95=AD=EB=AA=A9=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 --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6c01878138..c0b28e6ab2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ HELP.md .gradle +.gradle-user-home/ build/ !gradle/wrapper/gradle-wrapper.jar !**/src/main/** From 6d7f63ef31536d2c0737b859d4a697c07ec23156 Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sat, 28 Mar 2026 15:19:56 +0900 Subject: [PATCH 72/82] =?UTF-8?q?refactor:=20null=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EB=8D=98=20=EB=A1=9C=EC=A7=81=EC=9D=84=20Optional=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9=ED=95=98=EC=97=AC=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/Board.java | 4 ++-- src/main/java/domain/Piece.java | 7 ++----- src/main/java/io/OutputView.java | 12 +++++++----- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index a116bd6515..c788d4a21a 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -15,8 +15,8 @@ public Board(Map pieces) { public List getBlockingPieces(Route route) { return route.intermeidateNodes().stream() - .map(pieces::get) - .filter(piece -> piece != null) + .map(this::findPiece) + .flatMap(Optional::stream) .toList(); } diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/Piece.java index f6e68fb2ac..1603c3c006 100644 --- a/src/main/java/domain/Piece.java +++ b/src/main/java/domain/Piece.java @@ -47,11 +47,8 @@ public static Piece of(TeamColor teamColor, PieceType pieceType) { } private static MoveStrategy createMoveStrategy(PieceType pieceType) { - MoveStrategy moveStrategy = MOVE_STRATEGIES.get(pieceType); - if (moveStrategy != null) { - return moveStrategy; - } - throw new IllegalArgumentException("지원하지 않는 기물 타입입니다."); + return Optional.ofNullable(MOVE_STRATEGIES.get(pieceType)) + .orElseThrow(() -> new IllegalArgumentException("지원하지 않는 기물 타입입니다.")); } private static Map createMoveStrategies() { diff --git a/src/main/java/io/OutputView.java b/src/main/java/io/OutputView.java index a3d61e0c26..88c24ad258 100644 --- a/src/main/java/io/OutputView.java +++ b/src/main/java/io/OutputView.java @@ -8,6 +8,7 @@ import domain.TeamColor; import java.util.List; import java.util.Map; +import java.util.Optional; public class OutputView { @@ -58,7 +59,7 @@ public void printBoard(Board board) { StringBuilder line = new StringBuilder(); line.append(String.format("%2d │", row)); for (int column = 0; column <= 8; column++) { - Piece piece = board.findPiece(Position.of(row, column)).orElse(null); + Optional piece = board.findPiece(Position.of(row, column)); line.append(" ").append(formatBoardCell(piece)).append(" │"); } System.out.println(line); @@ -77,13 +78,14 @@ public void printError(String message) { System.out.println("[ERROR] " + message); } - private String formatBoardCell(Piece piece) { - if (piece == null) { + private String formatBoardCell(Optional piece) { + if (piece.isEmpty()) { return " "; } - String symbol = formatBoardSymbol(piece); + Piece actualPiece = piece.get(); + String symbol = formatBoardSymbol(actualPiece); - if (piece.getTeamColor() == TeamColor.CHO) { + if (actualPiece.getTeamColor() == TeamColor.CHO) { return CHO_COLOR + symbol + RESET; } return HAN_COLOR + symbol + RESET; From a0109b9290bffb7a51356e750f101c984be04fb3 Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sat, 28 Mar 2026 15:20:15 +0900 Subject: [PATCH 73/82] =?UTF-8?q?docs:=20=EC=82=AC=EC=9D=B4=ED=81=B41=20?= =?UTF-8?q?=EB=AF=B8=EC=85=98=20=EA=B8=B0=EB=A1=9D=20=EB=82=B4=EC=9A=A9=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 --- docs/cycle1_mission_record.md | 58 +++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/docs/cycle1_mission_record.md b/docs/cycle1_mission_record.md index b9fd9db760..a15906b805 100644 --- a/docs/cycle1_mission_record.md +++ b/docs/cycle1_mission_record.md @@ -20,26 +20,7 @@ default List makeRoutes(Position curPos, TeamColor teamColor) { List paths = getPaths(teamColor); for (MovePath path : paths) { - List steps = path.steps(); - Position currentPos = curPos; - List intermediates = new ArrayList<>(); - - for (int i = 0; i < steps.size(); i++) { - try { - currentPos = currentPos.next(steps.get(i)); - } catch (IllegalArgumentException exception) { - currentPos = null; - break; - } - - if (i < steps.size() - 1) { - intermediates.add(currentPos); - } - } - if (currentPos == null) { - continue; - } - validRoutes.add(new Route(curPos, currentPos, intermediates)); + createRoute(curPos, path.steps()).ifPresent(validRoutes::add); } return validRoutes; @@ -102,15 +83,39 @@ public class Position { - setter를 제공하지 않는다. - 모든 필드는 final로 선언하는 것을 기본으로 한다. -이 규칙을 적용하면서 `MovePath`, `Route`, `Row`, `Column`을 record/불변 객체로 유지하는 방향으로 설계를 잡았다. +이 규칙을 적용하면서 "값이 없음"을 `null` 대신 `Optional`로 다루도록 수정했다. + +예를 들어 보드 출력에서는 원래 빈 칸을 표현하기 위해 `orElse(null)`을 사용했지만, 현재는 `Optional`를 그대로 전달한다. + +```java +for (int column = 0; column <= 8; column++) { + Optional piece = board.findPiece(Position.of(row, column)); + line.append(" ").append(formatBoardCell(piece)).append(" │"); +} +``` + +```java +private String formatBoardCell(Optional piece) { + if (piece.isEmpty()) { + return " "; + } + Piece actualPiece = piece.get(); + ... +} +``` -특히 `Route`를 mutable 객체로 두고 이동 중간에 값을 채워 넣는 대신, 경로 계산이 끝났을 때 완성된 값으로 한 번에 생성했다. +또한 중간 기물 조회도 `Map.get()` 결과를 직접 `null` 비교하지 않고 `Optional::stream`으로 처리한다. ```java -validRoutes.add(new Route(curPos, currentPos, intermediates)); +public List getBlockingPieces(Route route) { + return route.intermeidateNodes().stream() + .map(this::findPiece) + .flatMap(Optional::stream) + .toList(); +} ``` -이렇게 해두면 경로 판정 로직이 `Route`를 수정하지 않고 읽기만 하면 되어서, 이후 `Board`, `MoveStrategy`, `Piece` 협력에서도 데이터 흐름이 단순해진다. +반면 `Position.equals(Object o)`의 `o == null` 검사는 자바의 동등성 비교 계약을 지키기 위한 표준 구현으로 보고 유지했다. 이 코드는 도메인 상태를 `null`로 표현하는 것이 아니라, 외부에서 전달된 비교 대상의 유효성을 검사하는 로직이기 때문에 유지하기로 했다. ## 4. 조건문을 다형성으로 대체한 코드 1곳 @@ -171,7 +176,7 @@ public class RookMoveStrategy implements MoveStrategy { } ``` -아직 `Piece.createMoveStrategy()` 내부에는 `PieceType`에 따른 조건문이 남아 있다. 다만 핵심 이동 규칙 자체는 `MoveStrategy` 다형성으로 분리되어 있고, 실제 행동 차이는 각 구현체가 맡고 있다는 점에서 "한 곳에서 모든 규칙을 조건문으로 처리하던 구조"보다는 훨씬 나아졌다. +`Piece.createMoveStrategy()`도 현재는 `EnumMap` 조회로 전략을 연결하고 있다. 핵심 이동 규칙 자체는 `MoveStrategy` 다형성으로 분리되어 있고, 실제 행동 차이는 각 구현체가 맡고 있다는 점에서 "한 곳에서 모든 규칙을 조건문으로 처리하던 구조"보다 책임이 명확해졌다. ## 5. 인터페이스/추상클래스를 도입한 이유 @@ -259,4 +264,5 @@ public class InnerFormationStrategy extends InitialFormationStrategy { 초기 배치에 포함해야 한다면 `InitialFormationStrategy` 계열에서 좌표만 추가하면 되고, 테스트는 "경로 생성 테스트", "차단/포획 판정 테스트", "초기 배치 테스트" 에 새 기물에 대한 케이스를 추가하면 된다. -지금 구조에서는 새 기물 추가 시 수정 지점이 완전히 없지는 않지만, "이동 규칙", "전략 연결", "초기 배치", "테스트"로 범위를 예측 가능하다. \ No newline at end of file +지금 구조에서는 새 기물 추가 시 수정 지점이 완전히 없지는 않지만, "이동 규칙", "전략 연결", "초기 배치", "테스트"로 범위를 예측 가능하다. + From b750fcb7af4f71d4bb972ccdec55792c034303d9 Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sat, 28 Mar 2026 15:23:23 +0900 Subject: [PATCH 74/82] =?UTF-8?q?refactor:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20BlockingPieces=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/domain/BlockingPieces.java | 47 ------------------------ 1 file changed, 47 deletions(-) delete mode 100644 src/main/java/domain/BlockingPieces.java diff --git a/src/main/java/domain/BlockingPieces.java b/src/main/java/domain/BlockingPieces.java deleted file mode 100644 index 751de2681b..0000000000 --- a/src/main/java/domain/BlockingPieces.java +++ /dev/null @@ -1,47 +0,0 @@ -package domain; - -import java.util.List; - -public class BlockingPieces { - - private int MAX_PIECES_ON_ROUTE = 2; - private final List pieces; - - public BlockingPieces(List pieces) { - if (pieces.size() > MAX_PIECES_ON_ROUTE) { - throw new IllegalArgumentException("경로 상의 기물은 최대 "+ MAX_PIECES_ON_ROUTE+ "개만 존재할 수 있습니다."); - } - this.pieces = List.copyOf(pieces); - } - - public boolean isFirstPieceCannon() { - if (pieces.isEmpty()) { - return false; - } - return pieces.getFirst().getPieceType() == PieceType.CANNON; // Java 21+ 문법 - } - - - public boolean isLastPieceCannon() { - if (pieces.size() < MAX_PIECES_ON_ROUTE) { - return false; - } - return pieces.getLast().getPieceType() == PieceType.CANNON; - } - - public boolean isLastPieceSameTeam(TeamColor myTeam) { - if (pieces.size() < MAX_PIECES_ON_ROUTE) { - return false; - } - return pieces.getLast().getTeamColor() == myTeam; - } - - public int size() { - return pieces.size(); - } - - public TeamColor getFirstBlockingTeamColor() { - return pieces.getFirst().getTeamColor(); - } - -} \ No newline at end of file From a68b09009f2164d11c3312968674a65f4ba0eb90 Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sat, 28 Mar 2026 15:46:32 +0900 Subject: [PATCH 75/82] =?UTF-8?q?refactor:=20=EB=A7=A4=EC=A7=81=EB=84=98?= =?UTF-8?q?=EB=B2=84=20=EB=B0=8F=20=EB=AC=B8=EC=9E=90=EC=97=B4=20=EC=83=81?= =?UTF-8?q?=EC=88=98=EB=A1=9C=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Initializer.java | 4 +- src/main/java/Runner.java | 17 +- src/main/java/domain/Board.java | 10 +- src/main/java/domain/Position.java | 6 +- src/main/java/io/InputView.java | 9 +- src/main/java/io/OutputView.java | 152 +++++++++--------- .../formation/InitialFormationStrategy.java | 57 ++++--- .../formation/InnerFormationStrategy.java | 28 ++-- .../formation/LeftFormationStrategy.java | 16 +- .../formation/OuterFormationStrategy.java | 16 +- .../formation/RightFormationStrategy.java | 16 +- .../strategy/move/CannonMoveStrategy.java | 15 +- src/main/java/strategy/move/MoveStrategy.java | 10 +- .../java/strategy/move/RookMoveStrategy.java | 8 +- 14 files changed, 202 insertions(+), 162 deletions(-) diff --git a/src/main/java/Initializer.java b/src/main/java/Initializer.java index 09fec35ed0..542365d0e0 100644 --- a/src/main/java/Initializer.java +++ b/src/main/java/Initializer.java @@ -8,8 +8,8 @@ public class Initializer { - private InitialFormationStrategy choStrategy; - private InitialFormationStrategy hanStrategy; + private final InitialFormationStrategy choStrategy; + private final InitialFormationStrategy hanStrategy; public Initializer(InitialFormationStrategy choStrategy, InitialFormationStrategy hanStrategy) { this.choStrategy = choStrategy; diff --git a/src/main/java/Runner.java b/src/main/java/Runner.java index 8fc6d7ead1..c9970858f2 100644 --- a/src/main/java/Runner.java +++ b/src/main/java/Runner.java @@ -16,6 +16,9 @@ import strategy.formation.RightFormationStrategy; public class Runner { + private static final int FIRST_OPTION_NUMBER = 1; + private static final int BACK_OPTION_NUMBER = 0; + private static final int ZERO_BASE_INDEX_OFFSET = 1; private static final List FORMATIONS = List.of( new InnerFormationStrategy(), new OuterFormationStrategy(), @@ -90,11 +93,11 @@ private void playTurn(Board board) { private InitialFormationStrategy createFormationStrategy(int choice) { validateFormationChoice(choice); - return FORMATIONS.get(choice - 1); + return FORMATIONS.get(choice - ZERO_BASE_INDEX_OFFSET); } private void validateFormationChoice(int choice) { - if (choice >= 1 && choice <= FORMATIONS.size()) { + if (choice >= FIRST_OPTION_NUMBER && choice <= FORMATIONS.size()) { return; } throw new IllegalArgumentException("상차림 번호는 1~4 사이여야 합니다."); @@ -114,7 +117,7 @@ private Optional chooseRoute(Board board, Piece selectedPiece) { outputView.printRouteOptions(routes); int routeChoice = inputView.readRouteChoice(); - if (routeChoice == 0) { + if (routeChoice == BACK_OPTION_NUMBER) { return Optional.empty(); } return Optional.of(getSelectedRoute(routes, routeChoice)); @@ -127,16 +130,16 @@ private void validateMovableRoutes(List routes) { } private Piece getSelectedPiece(List> pieces, int pieceChoice) { - if (pieceChoice < 1 || pieceChoice > pieces.size()) { + if (pieceChoice < FIRST_OPTION_NUMBER || pieceChoice > pieces.size()) { throw new IllegalArgumentException("기물 번호가 범위를 벗어났습니다."); } - return pieces.get(pieceChoice - 1).getValue(); + return pieces.get(pieceChoice - ZERO_BASE_INDEX_OFFSET).getValue(); } private Route getSelectedRoute(List routes, int routeChoice) { - if (routeChoice < 1 || routeChoice > routes.size()) { + if (routeChoice < FIRST_OPTION_NUMBER || routeChoice > routes.size()) { throw new IllegalArgumentException("경로 번호가 범위를 벗어났습니다."); } - return routes.get(routeChoice - 1); + return routes.get(routeChoice - ZERO_BASE_INDEX_OFFSET); } } diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/Board.java index c788d4a21a..daf90c3383 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/Board.java @@ -49,7 +49,7 @@ public List> findPiecesByTeam(TeamColor teamColor) { } public List findMovableRoutes(Piece piece) { - Position currentPosition = findPositionOf(piece) + final Position currentPosition = findPositionOf(piece) .orElseThrow(() -> new IllegalArgumentException("보드에 없는 기물입니다.")); return piece.makeRoutes(currentPosition).stream() @@ -59,16 +59,16 @@ public List findMovableRoutes(Piece piece) { } public void move(Piece piece, Position destination) { - Position currentPosition = findPositionOf(piece) + final Position currentPosition = findPositionOf(piece) .orElseThrow(() -> new IllegalArgumentException("보드에 없는 기물입니다.")); - Route route = piece.makeRoutes(currentPosition).stream() + final Route route = piece.makeRoutes(currentPosition).stream() .filter(candidate -> candidate.endPos().equals(destination)) .findFirst() .orElseThrow(() -> new IllegalArgumentException("해당 기물은 목적지로 이동할 수 없습니다.")); - List blockingPieces = getBlockingPieces(route); - Optional destinationPiece = getDestinationPiece(route); + final List blockingPieces = getBlockingPieces(route); + final Optional destinationPiece = getDestinationPiece(route); if (!piece.canMove(route, blockingPieces, destinationPiece)) { throw new IllegalArgumentException("현재 판 상태에서는 해당 목적지로 이동할 수 없습니다."); diff --git a/src/main/java/domain/Position.java b/src/main/java/domain/Position.java index 02c7eaaba1..98d439cbf4 100644 --- a/src/main/java/domain/Position.java +++ b/src/main/java/domain/Position.java @@ -12,8 +12,8 @@ private Position(Row row, Column column) { } public Position next(Direction direction) { - int nextRow = this.row.value() + direction.dRow(); - int nextCol = this.column.value() + direction.dColumn(); + final int nextRow = this.row.value() + direction.dRow(); + final int nextCol = this.column.value() + direction.dColumn(); return Position.of(nextRow, nextCol); } @@ -38,7 +38,7 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { return false; } - Position position = (Position) o; + final Position position = (Position) o; return Objects.equals(row, position.row) && Objects.equals(column, position.column); } diff --git a/src/main/java/io/InputView.java b/src/main/java/io/InputView.java index eb844b3aa8..02f79f5038 100644 --- a/src/main/java/io/InputView.java +++ b/src/main/java/io/InputView.java @@ -4,6 +4,9 @@ import java.util.Scanner; public class InputView { + private static final String FORMATION_CHOICE_PROMPT = " 상차림 선택 (1. 안상 2. 바깥상 3. 좌상 4. 우상) > "; + private static final String PIECE_CHOICE_PROMPT = " 차례, 선택할 기물 번호 > "; + private static final String ROUTE_CHOICE_PROMPT = "이동할 경로 번호 선택 (0은 뒤로가기) > "; private final Scanner scanner; @@ -16,17 +19,17 @@ public InputView(Scanner scanner) { } public int readFormationChoice(TeamColor teamColor) { - System.out.print(teamColor.displayName() + " 상차림 선택 (1. 안상 2. 바깥상 3. 좌상 4. 우상) > "); + System.out.print(teamColor.displayName() + FORMATION_CHOICE_PROMPT); return Integer.parseInt(scanner.nextLine().trim()); } public int readPieceChoice(TeamColor teamColor) { - System.out.print(teamColor.displayName() + " 차례, 선택할 기물 번호 > "); + System.out.print(teamColor.displayName() + PIECE_CHOICE_PROMPT); return Integer.parseInt(scanner.nextLine().trim()); } public int readRouteChoice() { - System.out.print("이동할 경로 번호 선택 (0은 뒤로가기) > "); + System.out.print(ROUTE_CHOICE_PROMPT); return Integer.parseInt(scanner.nextLine().trim()); } diff --git a/src/main/java/io/OutputView.java b/src/main/java/io/OutputView.java index 88c24ad258..f1af55c026 100644 --- a/src/main/java/io/OutputView.java +++ b/src/main/java/io/OutputView.java @@ -6,84 +6,109 @@ import domain.Position; import domain.Route; import domain.TeamColor; +import java.util.EnumMap; import java.util.List; import java.util.Map; import java.util.Optional; public class OutputView { - + private static final int BOARD_LAST_ROW = 9; + private static final int BOARD_LAST_COLUMN = 8; + private static final String EMPTY_CELL = " "; + private static final String GAME_START_MESSAGE = "장기 게임을 시작합니다."; + private static final String FORMATION_SELECTION_MESSAGE = " 상차림을 선택하세요."; + private static final String INNER_FORMATION_OPTION = "1. 안상차림"; + private static final String OUTER_FORMATION_OPTION = "2. 바깥상차림"; + private static final String LEFT_FORMATION_OPTION = "3. 좌상차림"; + private static final String RIGHT_FORMATION_OPTION = "4. 우상차림"; + private static final String CURRENT_TURN_MESSAGE = "현재 턴: "; + private static final String PIECE_SELECTION_MESSAGE = "선택 가능한 기물:"; + private static final String ROUTE_SELECTION_MESSAGE = "이동 가능한 경로:"; + private static final String BACK_OPTION_MESSAGE = "0. 뒤로가기"; + private static final String CURRENT_BOARD_MESSAGE = "현재 장기판"; + private static final String BOARD_HEADER = " 0 1 2 3 4 5 6 7 8"; + private static final String BOARD_TOP_BORDER = " ┌────┬────┬────┬────┬────┬────┬────┬────┬────┐"; + private static final String BOARD_MIDDLE_BORDER = " ├────┼────┼────┼────┼────┼────┼────┼────┼────┤"; + private static final String BOARD_BOTTOM_BORDER = " └────┴────┴────┴────┴────┴────┴────┴────┴────┘"; + private static final String ROW_PREFIX_FORMAT = "%2d │"; + private static final String CELL_SEPARATOR = " │"; + private static final String ROUTE_FORMAT = "%d. %s -> %s"; + private static final String PIECE_OPTION_FORMAT = "%d. %s%s"; + private static final String MOVE_RESULT_FORMAT = "%s 가 %s 로 이동했습니다."; + private static final String ERROR_PREFIX = "[ERROR] "; + private static final Map PIECE_SYMBOLS = createPieceSymbols(); private static final String CHO_COLOR = "\u001B[38;5;71m"; private static final String HAN_COLOR = "\u001B[38;5;167m"; private static final String RESET = "\u001B[0m"; public void printGameStart() { - System.out.println("장기 게임을 시작합니다."); + System.out.println(GAME_START_MESSAGE); } public void printFormationSelectionPrompt(TeamColor teamColor) { - System.out.println(teamColor.displayName() + " 상차림을 선택하세요."); - System.out.println("1. 안상차림"); - System.out.println("2. 바깥상차림"); - System.out.println("3. 좌상차림"); - System.out.println("4. 우상차림"); + System.out.println(teamColor.displayName() + FORMATION_SELECTION_MESSAGE); + System.out.println(INNER_FORMATION_OPTION); + System.out.println(OUTER_FORMATION_OPTION); + System.out.println(LEFT_FORMATION_OPTION); + System.out.println(RIGHT_FORMATION_OPTION); } public void printCurrentTurn(TeamColor teamColor) { System.out.println(); - System.out.println("현재 턴: " + teamColor.displayName()); + System.out.println(CURRENT_TURN_MESSAGE + teamColor.displayName()); } public void printPieceOptions(List> pieces) { - System.out.println("선택 가능한 기물:"); + System.out.println(PIECE_SELECTION_MESSAGE); for (int index = 0; index < pieces.size(); index++) { - Map.Entry entry = pieces.get(index); - System.out.println((index + 1) + ". " + formatPiece(entry.getValue()) + entry.getKey()); + final Map.Entry entry = pieces.get(index); + System.out.println(PIECE_OPTION_FORMAT.formatted(index + 1, formatPiece(entry.getValue()), entry.getKey())); } } public void printRouteOptions(List routes) { - System.out.println("이동 가능한 경로:"); - System.out.println("0. 뒤로가기"); + System.out.println(ROUTE_SELECTION_MESSAGE); + System.out.println(BACK_OPTION_MESSAGE); for (int index = 0; index < routes.size(); index++) { - Route route = routes.get(index); - System.out.println((index + 1) + ". " + route.startPos() + " -> " + route.endPos()); + final Route route = routes.get(index); + System.out.println(ROUTE_FORMAT.formatted(index + 1, route.startPos(), route.endPos())); } } public void printBoard(Board board) { System.out.println(); - System.out.println("현재 장기판"); - System.out.println(" 0 1 2 3 4 5 6 7 8"); - System.out.println(" ┌────┬────┬────┬────┬────┬────┬────┬────┬────┐"); - for (int row = 0; row <= 9; row++) { - StringBuilder line = new StringBuilder(); - line.append(String.format("%2d │", row)); - for (int column = 0; column <= 8; column++) { - Optional piece = board.findPiece(Position.of(row, column)); - line.append(" ").append(formatBoardCell(piece)).append(" │"); + System.out.println(CURRENT_BOARD_MESSAGE); + System.out.println(BOARD_HEADER); + System.out.println(BOARD_TOP_BORDER); + for (int row = 0; row <= BOARD_LAST_ROW; row++) { + final StringBuilder line = new StringBuilder(); + line.append(ROW_PREFIX_FORMAT.formatted(row)); + for (int column = 0; column <= BOARD_LAST_COLUMN; column++) { + final Optional piece = board.findPiece(Position.of(row, column)); + line.append(" ").append(formatBoardCell(piece)).append(CELL_SEPARATOR); } System.out.println(line); - if (row < 9) { - System.out.println(" ├────┼────┼────┼────┼────┼────┼────┼────┼────┤"); + if (row < BOARD_LAST_ROW) { + System.out.println(BOARD_MIDDLE_BORDER); } } - System.out.println(" └────┴────┴────┴────┴────┴────┴────┴────┴────┘"); + System.out.println(BOARD_BOTTOM_BORDER); } public void printMoveResult(Piece piece, Position destination) { - System.out.println(formatPiece(piece) + " 가 " + destination + " 로 이동했습니다."); + System.out.println(MOVE_RESULT_FORMAT.formatted(formatPiece(piece), destination)); } public void printError(String message) { - System.out.println("[ERROR] " + message); + System.out.println(ERROR_PREFIX + message); } private String formatBoardCell(Optional piece) { if (piece.isEmpty()) { - return " "; + return EMPTY_CELL; } - Piece actualPiece = piece.get(); - String symbol = formatBoardSymbol(actualPiece); + final Piece actualPiece = piece.get(); + final String symbol = formatBoardSymbol(actualPiece); if (actualPiece.getTeamColor() == TeamColor.CHO) { return CHO_COLOR + symbol + RESET; @@ -92,52 +117,27 @@ private String formatBoardCell(Optional piece) { } private String formatPiece(Piece piece) { - if (piece.getPieceType() == PieceType.ROOK) { - return "차"; - } - if (piece.getPieceType() == PieceType.HORSE) { - return "마"; - } - if (piece.getPieceType() == PieceType.ELEPHANT) { - return "상"; - } - if (piece.getPieceType() == PieceType.GUARD) { - return "사"; - } - if (piece.getPieceType() == PieceType.KING) { - return "왕"; - } - if (piece.getPieceType() == PieceType.CANNON) { - return "포"; - } - if (piece.getPieceType() == PieceType.PAWN) { - return "졸"; - } - throw new IllegalArgumentException("지원하지 않는 기물 타입입니다."); + return findPieceSymbol(piece.getPieceType()); } private String formatBoardSymbol(Piece piece) { - if (piece.getPieceType() == PieceType.ROOK) { - return "차"; - } - if (piece.getPieceType() == PieceType.HORSE) { - return "마"; - } - if (piece.getPieceType() == PieceType.ELEPHANT) { - return "상"; - } - if (piece.getPieceType() == PieceType.GUARD) { - return "사"; - } - if (piece.getPieceType() == PieceType.KING) { - return "왕"; - } - if (piece.getPieceType() == PieceType.CANNON) { - return "포"; - } - if (piece.getPieceType() == PieceType.PAWN) { - return "졸"; - } - throw new IllegalArgumentException("지원하지 않는 기물 타입입니다."); + return findPieceSymbol(piece.getPieceType()); + } + + private String findPieceSymbol(PieceType pieceType) { + return Optional.ofNullable(PIECE_SYMBOLS.get(pieceType)) + .orElseThrow(() -> new IllegalArgumentException("지원하지 않는 기물 타입입니다.")); + } + + private static Map createPieceSymbols() { + final Map pieceSymbols = new EnumMap<>(PieceType.class); + pieceSymbols.put(PieceType.ROOK, "차"); + pieceSymbols.put(PieceType.HORSE, "마"); + pieceSymbols.put(PieceType.ELEPHANT, "상"); + pieceSymbols.put(PieceType.GUARD, "사"); + pieceSymbols.put(PieceType.KING, "왕"); + pieceSymbols.put(PieceType.CANNON, "포"); + pieceSymbols.put(PieceType.PAWN, "졸"); + return pieceSymbols; } } diff --git a/src/main/java/strategy/formation/InitialFormationStrategy.java b/src/main/java/strategy/formation/InitialFormationStrategy.java index b5943bf784..0b0e1d6599 100644 --- a/src/main/java/strategy/formation/InitialFormationStrategy.java +++ b/src/main/java/strategy/formation/InitialFormationStrategy.java @@ -8,12 +8,27 @@ import java.util.Map; public abstract class InitialFormationStrategy { + protected static final int HAN_BACK_RANK_ROW = 0; + protected static final int CHO_BACK_RANK_ROW = 9; + private static final int HAN_KING_ROW = 1; + private static final int HAN_CANNON_ROW = 2; + private static final int HAN_PAWN_ROW = 3; + private static final int CHO_KING_ROW = 8; + private static final int CHO_CANNON_ROW = 7; + private static final int CHO_PAWN_ROW = 6; + private static final int LEFT_EDGE_COLUMN = 0; + private static final int LEFT_CANNON_COLUMN = 1; + private static final int PALACE_LEFT_GUARD_COLUMN = 3; + private static final int PALACE_CENTER_COLUMN = 4; + private static final int PALACE_RIGHT_GUARD_COLUMN = 5; + private static final int RIGHT_CANNON_COLUMN = 7; + private static final int RIGHT_EDGE_COLUMN = 8; + private static final int PAWN_COLUMN_INTERVAL = 2; public final Map setUpPieces(TeamColor teamColor) { - - Map formationPieces = setupFormation(teamColor); - Map fixedPieces = placeFixedPieces(teamColor); - Map allPieces = new HashMap<>(); + final Map formationPieces = setupFormation(teamColor); + final Map fixedPieces = placeFixedPieces(teamColor); + final Map allPieces = new HashMap<>(); allPieces.putAll(formationPieces); allPieces.putAll(fixedPieces); @@ -23,33 +38,35 @@ public final Map setUpPieces(TeamColor teamColor) { protected abstract Map setupFormation(TeamColor teamColor); + protected final int findBackRankRow(TeamColor teamColor) { + if (teamColor == TeamColor.CHO) { + return CHO_BACK_RANK_ROW; + } + return HAN_BACK_RANK_ROW; + } + private Map placeFixedPieces(TeamColor teamColor) { if (teamColor == TeamColor.HAN) { - return createFixedMap(teamColor, 0, 1, 2, 3); + return createFixedMap(teamColor, HAN_BACK_RANK_ROW, HAN_KING_ROW, HAN_CANNON_ROW, HAN_PAWN_ROW); } - return createFixedMap(teamColor, 9, 8, 7, 6); + return createFixedMap(teamColor, CHO_BACK_RANK_ROW, CHO_KING_ROW, CHO_CANNON_ROW, CHO_PAWN_ROW); } private Map createFixedMap(TeamColor teamColor, int backRankRow, int kingRow, int cannonRow, int pawnRow) { - Map map = new HashMap<>(); + final Map map = new HashMap<>(); - // 1. 차 (ROOK) - 양쪽 맨 끝 (column = 0, 8) - map.put(Position.of(backRankRow, 0), Piece.of(teamColor, PieceType.ROOK)); - map.put(Position.of(backRankRow, 8), Piece.of(teamColor, PieceType.ROOK)); + map.put(Position.of(backRankRow, LEFT_EDGE_COLUMN), Piece.of(teamColor, PieceType.ROOK)); + map.put(Position.of(backRankRow, RIGHT_EDGE_COLUMN), Piece.of(teamColor, PieceType.ROOK)); - // 2. 사 (GUARD) - 궁성 안쪽 귀 (column = 3, 5) - map.put(Position.of(backRankRow, 3), Piece.of(teamColor, PieceType.GUARD)); - map.put(Position.of(backRankRow, 5), Piece.of(teamColor, PieceType.GUARD)); + map.put(Position.of(backRankRow, PALACE_LEFT_GUARD_COLUMN), Piece.of(teamColor, PieceType.GUARD)); + map.put(Position.of(backRankRow, PALACE_RIGHT_GUARD_COLUMN), Piece.of(teamColor, PieceType.GUARD)); - // 3. 왕 (KING) - 궁성 중앙 (column = 4) - map.put(Position.of(kingRow, 4), Piece.of(teamColor, PieceType.KING)); + map.put(Position.of(kingRow, PALACE_CENTER_COLUMN), Piece.of(teamColor, PieceType.KING)); - // 4. 포 (CANNON) - (column = 1, 7) - map.put(Position.of(cannonRow, 1), Piece.of(teamColor, PieceType.CANNON)); - map.put(Position.of(cannonRow, 7), Piece.of(teamColor, PieceType.CANNON)); + map.put(Position.of(cannonRow, LEFT_CANNON_COLUMN), Piece.of(teamColor, PieceType.CANNON)); + map.put(Position.of(cannonRow, RIGHT_CANNON_COLUMN), Piece.of(teamColor, PieceType.CANNON)); - // 5. 졸/병 (PAWN) - 5개 (column = 0, 2, 4, 6, 8) - for (int column = 0; column <= 8; column += 2) { + for (int column = LEFT_EDGE_COLUMN; column <= RIGHT_EDGE_COLUMN; column += PAWN_COLUMN_INTERVAL) { map.put(Position.of(pawnRow, column), Piece.of(teamColor, PieceType.PAWN)); } diff --git a/src/main/java/strategy/formation/InnerFormationStrategy.java b/src/main/java/strategy/formation/InnerFormationStrategy.java index 3b6e15dfcc..6776f2f425 100644 --- a/src/main/java/strategy/formation/InnerFormationStrategy.java +++ b/src/main/java/strategy/formation/InnerFormationStrategy.java @@ -8,25 +8,25 @@ import java.util.Map; public class InnerFormationStrategy extends InitialFormationStrategy { + private static final int LEFT_HORSE_COLUMN = 1; + private static final int LEFT_ELEPHANT_COLUMN = 2; + private static final int RIGHT_ELEPHANT_COLUMN = 6; + private static final int RIGHT_HORSE_COLUMN = 7; @Override protected Map setupFormation(TeamColor teamColor) { - Map formation = new HashMap<>(); - int row; if (teamColor.equals(TeamColor.CHO)) { - row = 9; - formation.put(Position.of(row, 1), Piece.of(teamColor, PieceType.HORSE)); - formation.put(Position.of(row, 2), Piece.of(teamColor, PieceType.ELEPHANT)); - formation.put(Position.of(row, 6), Piece.of(teamColor, PieceType.ELEPHANT)); - formation.put(Position.of(row, 7), Piece.of(teamColor, PieceType.HORSE)); - return formation; + return createFormation(teamColor, CHO_BACK_RANK_ROW); } - row = 0; - formation.put(Position.of(row, 1), Piece.of(teamColor, PieceType.HORSE)); - formation.put(Position.of(row, 2), Piece.of(teamColor, PieceType.ELEPHANT)); - formation.put(Position.of(row, 6), Piece.of(teamColor, PieceType.ELEPHANT)); - formation.put(Position.of(row, 7), Piece.of(teamColor, PieceType.HORSE)); - return formation; + return createFormation(teamColor, HAN_BACK_RANK_ROW); + } + private Map createFormation(TeamColor teamColor, int row) { + final Map formation = new HashMap<>(); + formation.put(Position.of(row, LEFT_HORSE_COLUMN), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(row, LEFT_ELEPHANT_COLUMN), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(row, RIGHT_ELEPHANT_COLUMN), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(row, RIGHT_HORSE_COLUMN), Piece.of(teamColor, PieceType.HORSE)); + return formation; } } diff --git a/src/main/java/strategy/formation/LeftFormationStrategy.java b/src/main/java/strategy/formation/LeftFormationStrategy.java index 7d3e5799a1..9d3e44a739 100644 --- a/src/main/java/strategy/formation/LeftFormationStrategy.java +++ b/src/main/java/strategy/formation/LeftFormationStrategy.java @@ -8,16 +8,20 @@ import java.util.Map; public class LeftFormationStrategy extends InitialFormationStrategy { + private static final int LEFT_HORSE_COLUMN = 1; + private static final int LEFT_ELEPHANT_COLUMN = 2; + private static final int RIGHT_HORSE_COLUMN = 6; + private static final int RIGHT_ELEPHANT_COLUMN = 7; @Override protected Map setupFormation(TeamColor teamColor) { - Map formation = new HashMap<>(); - int row = teamColor == TeamColor.CHO ? 9 : 0; + final Map formation = new HashMap<>(); + final int row = findBackRankRow(teamColor); - formation.put(Position.of(row, 1), Piece.of(teamColor, PieceType.HORSE)); - formation.put(Position.of(row, 2), Piece.of(teamColor, PieceType.ELEPHANT)); - formation.put(Position.of(row, 6), Piece.of(teamColor, PieceType.HORSE)); - formation.put(Position.of(row, 7), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(row, LEFT_HORSE_COLUMN), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(row, LEFT_ELEPHANT_COLUMN), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(row, RIGHT_HORSE_COLUMN), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(row, RIGHT_ELEPHANT_COLUMN), Piece.of(teamColor, PieceType.ELEPHANT)); return formation; } } diff --git a/src/main/java/strategy/formation/OuterFormationStrategy.java b/src/main/java/strategy/formation/OuterFormationStrategy.java index 2078528e38..c5a884e713 100644 --- a/src/main/java/strategy/formation/OuterFormationStrategy.java +++ b/src/main/java/strategy/formation/OuterFormationStrategy.java @@ -8,16 +8,20 @@ import java.util.Map; public class OuterFormationStrategy extends InitialFormationStrategy { + private static final int LEFT_ELEPHANT_COLUMN = 1; + private static final int LEFT_HORSE_COLUMN = 2; + private static final int RIGHT_HORSE_COLUMN = 6; + private static final int RIGHT_ELEPHANT_COLUMN = 7; @Override protected Map setupFormation(TeamColor teamColor) { - Map formation = new HashMap<>(); - int row = teamColor == TeamColor.CHO ? 9 : 0; + final Map formation = new HashMap<>(); + final int row = findBackRankRow(teamColor); - formation.put(Position.of(row, 1), Piece.of(teamColor, PieceType.ELEPHANT)); - formation.put(Position.of(row, 2), Piece.of(teamColor, PieceType.HORSE)); - formation.put(Position.of(row, 6), Piece.of(teamColor, PieceType.HORSE)); - formation.put(Position.of(row, 7), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(row, LEFT_ELEPHANT_COLUMN), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(row, LEFT_HORSE_COLUMN), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(row, RIGHT_HORSE_COLUMN), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(row, RIGHT_ELEPHANT_COLUMN), Piece.of(teamColor, PieceType.ELEPHANT)); return formation; } } diff --git a/src/main/java/strategy/formation/RightFormationStrategy.java b/src/main/java/strategy/formation/RightFormationStrategy.java index f5c3ff2319..8167c3be24 100644 --- a/src/main/java/strategy/formation/RightFormationStrategy.java +++ b/src/main/java/strategy/formation/RightFormationStrategy.java @@ -8,16 +8,20 @@ import java.util.Map; public class RightFormationStrategy extends InitialFormationStrategy { + private static final int LEFT_ELEPHANT_COLUMN = 1; + private static final int LEFT_HORSE_COLUMN = 2; + private static final int RIGHT_ELEPHANT_COLUMN = 6; + private static final int RIGHT_HORSE_COLUMN = 7; @Override protected Map setupFormation(TeamColor teamColor) { - Map formation = new HashMap<>(); - int row = teamColor == TeamColor.CHO ? 9 : 0; + final Map formation = new HashMap<>(); + final int row = findBackRankRow(teamColor); - formation.put(Position.of(row, 1), Piece.of(teamColor, PieceType.ELEPHANT)); - formation.put(Position.of(row, 2), Piece.of(teamColor, PieceType.HORSE)); - formation.put(Position.of(row, 6), Piece.of(teamColor, PieceType.ELEPHANT)); - formation.put(Position.of(row, 7), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(row, LEFT_ELEPHANT_COLUMN), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(row, LEFT_HORSE_COLUMN), Piece.of(teamColor, PieceType.HORSE)); + formation.put(Position.of(row, RIGHT_ELEPHANT_COLUMN), Piece.of(teamColor, PieceType.ELEPHANT)); + formation.put(Position.of(row, RIGHT_HORSE_COLUMN), Piece.of(teamColor, PieceType.HORSE)); return formation; } } diff --git a/src/main/java/strategy/move/CannonMoveStrategy.java b/src/main/java/strategy/move/CannonMoveStrategy.java index 4bf36c9d4c..daed5f2275 100644 --- a/src/main/java/strategy/move/CannonMoveStrategy.java +++ b/src/main/java/strategy/move/CannonMoveStrategy.java @@ -11,10 +11,13 @@ import java.util.Optional; public class CannonMoveStrategy implements MoveStrategy { + private static final int MIN_DISTANCE = 1; + private static final int MAX_STRAIGHT_DISTANCE = 9; + private static final int REQUIRED_BRIDGE_COUNT = 1; @Override public List getPaths(TeamColor teamColor) { - List paths = new ArrayList<>(); + final List paths = new ArrayList<>(); addStraightPaths(paths, Direction.NORTH); addStraightPaths(paths, Direction.SOUTH); @@ -25,8 +28,8 @@ public List getPaths(TeamColor teamColor) { } private void addStraightPaths(List paths, Direction direction) { - for (int distance = 1; distance <= 9; distance++) { - List steps = new ArrayList<>(); + for (int distance = MIN_DISTANCE; distance <= MAX_STRAIGHT_DISTANCE; distance++) { + final List steps = new ArrayList<>(); for (int i = 0; i < distance; i++) { steps.add(direction); } @@ -36,11 +39,11 @@ private void addStraightPaths(List paths, Direction direction) { @Override public boolean canMove(Route route, List blockingPieces, Optional destinationPiece, TeamColor myTeam) { - if (blockingPieces.size() != 1) { + if (blockingPieces.size() != REQUIRED_BRIDGE_COUNT) { return false; } - Piece bridgePiece = blockingPieces.getFirst(); + final Piece bridgePiece = blockingPieces.getFirst(); if (bridgePiece.getPieceType() == PieceType.CANNON) { return false; } @@ -49,7 +52,7 @@ public boolean canMove(Route route, List blockingPieces, Optional return true; } - Piece targetPiece = destinationPiece.get(); + final Piece targetPiece = destinationPiece.get(); if (targetPiece.getPieceType() == PieceType.CANNON) { return false; } diff --git a/src/main/java/strategy/move/MoveStrategy.java b/src/main/java/strategy/move/MoveStrategy.java index 8a7d72f8c5..2c90bd6c76 100644 --- a/src/main/java/strategy/move/MoveStrategy.java +++ b/src/main/java/strategy/move/MoveStrategy.java @@ -15,10 +15,10 @@ public interface MoveStrategy { List getPaths(TeamColor teamColor); default List makeRoutes(Position curPos, TeamColor teamColor) { - List validRoutes = new ArrayList<>(); - List paths = getPaths(teamColor); + final List validRoutes = new ArrayList<>(); + final List paths = getPaths(teamColor); - for (MovePath path : paths) { + for (final MovePath path : paths) { createRoute(curPos, path.steps()).ifPresent(validRoutes::add); } @@ -26,11 +26,11 @@ default List makeRoutes(Position curPos, TeamColor teamColor) { } private Optional createRoute(Position startPos, List steps) { + final List intermediates = new ArrayList<>(); Position currentPos = startPos; - List intermediates = new ArrayList<>(); for (int index = 0; index < steps.size(); index++) { - Optional nextPosition = findNextPosition(currentPos, steps.get(index)); + final Optional nextPosition = findNextPosition(currentPos, steps.get(index)); if (nextPosition.isEmpty()) { return Optional.empty(); } diff --git a/src/main/java/strategy/move/RookMoveStrategy.java b/src/main/java/strategy/move/RookMoveStrategy.java index 9dfa1cec8c..3d42b766c2 100644 --- a/src/main/java/strategy/move/RookMoveStrategy.java +++ b/src/main/java/strategy/move/RookMoveStrategy.java @@ -7,10 +7,12 @@ import java.util.List; public class RookMoveStrategy implements MoveStrategy { + private static final int MIN_DISTANCE = 1; + private static final int MAX_STRAIGHT_DISTANCE = 9; @Override public List getPaths(TeamColor teamColor) { - List paths = new ArrayList<>(); + final List paths = new ArrayList<>(); addStraightPaths(paths, Direction.NORTH); addStraightPaths(paths, Direction.SOUTH); @@ -21,8 +23,8 @@ public List getPaths(TeamColor teamColor) { } private void addStraightPaths(List paths, Direction direction) { - for (int distance = 1; distance <= 9; distance++) { - List steps = new ArrayList<>(); + for (int distance = MIN_DISTANCE; distance <= MAX_STRAIGHT_DISTANCE; distance++) { + final List steps = new ArrayList<>(); for (int i = 0; i < distance; i++) { steps.add(direction); } From 0740d02273558c4af63122a5d0dc23c21e612f62 Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sat, 28 Mar 2026 15:54:24 +0900 Subject: [PATCH 76/82] =?UTF-8?q?refactor:=20=EC=9E=AC=ED=95=A0=EB=8B=B9?= =?UTF-8?q?=20=EC=97=86=EB=8A=94=20=EA=B0=92=EC=97=90=20final=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Initializer.java | 2 +- src/main/java/Runner.java | 14 +++++++------- src/main/java/domain/Piece.java | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/Initializer.java b/src/main/java/Initializer.java index 542365d0e0..a1e72b0d7d 100644 --- a/src/main/java/Initializer.java +++ b/src/main/java/Initializer.java @@ -17,7 +17,7 @@ public Initializer(InitialFormationStrategy choStrategy, InitialFormationStrateg } public Board initialize() { - Map board = new HashMap<>(); + final Map board = new HashMap<>(); board.putAll(choStrategy.setUpPieces(TeamColor.CHO)); board.putAll(hanStrategy.setUpPieces(TeamColor.HAN)); return new Board(board); diff --git a/src/main/java/Runner.java b/src/main/java/Runner.java index c9970858f2..e5d9397aad 100644 --- a/src/main/java/Runner.java +++ b/src/main/java/Runner.java @@ -68,19 +68,19 @@ private InitialFormationStrategy chooseFormationStrategy(TeamColor teamColor) { } private void playTurn(Board board) { - TeamColor currentTurn = turnManager.getCurrentTurn(); + final TeamColor currentTurn = turnManager.getCurrentTurn(); outputView.printCurrentTurn(currentTurn); outputView.printBoard(board); while (true) { try { - Piece selectedPiece = choosePiece(board, currentTurn); - Optional selectedRoute = chooseRoute(board, selectedPiece); + final Piece selectedPiece = choosePiece(board, currentTurn); + final Optional selectedRoute = chooseRoute(board, selectedPiece); if (selectedRoute.isEmpty()) { continue; } - Position destination = selectedRoute.get().endPos(); + final Position destination = selectedRoute.get().endPos(); board.move(selectedPiece, destination); outputView.printMoveResult(selectedPiece, destination); turnManager.progressTurn(); @@ -107,16 +107,16 @@ private Piece choosePiece(Board board, TeamColor currentTurn) { List> pieces = board.findPiecesByTeam(currentTurn); outputView.printPieceOptions(pieces); - int pieceChoice = inputView.readPieceChoice(currentTurn); + final int pieceChoice = inputView.readPieceChoice(currentTurn); return getSelectedPiece(pieces, pieceChoice); } private Optional chooseRoute(Board board, Piece selectedPiece) { - List routes = board.findMovableRoutes(selectedPiece); + final List routes = board.findMovableRoutes(selectedPiece); validateMovableRoutes(routes); outputView.printRouteOptions(routes); - int routeChoice = inputView.readRouteChoice(); + final int routeChoice = inputView.readRouteChoice(); if (routeChoice == BACK_OPTION_NUMBER) { return Optional.empty(); } diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/Piece.java index 1603c3c006..7389990b89 100644 --- a/src/main/java/domain/Piece.java +++ b/src/main/java/domain/Piece.java @@ -52,7 +52,7 @@ private static MoveStrategy createMoveStrategy(PieceType pieceType) { } private static Map createMoveStrategies() { - Map moveStrategies = new EnumMap<>(PieceType.class); + final Map moveStrategies = new EnumMap<>(PieceType.class); moveStrategies.put(PieceType.CANNON, new CannonMoveStrategy()); moveStrategies.put(PieceType.ELEPHANT, new ElephantMoveStrategy()); moveStrategies.put(PieceType.GUARD, new GuardMoveStrategy()); From f6b7213a01dc675e187618d1103626464c6fbd6f Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sat, 28 Mar 2026 16:09:24 +0900 Subject: [PATCH 77/82] =?UTF-8?q?fix:=20Row=EC=99=80=20Column=20=EC=9D=8C?= =?UTF-8?q?=EC=88=98=20=EC=9E=85=EB=A0=A5=20=EA=B2=80=EC=A6=9D=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/domain/Column.java | 4 ++++ src/main/java/domain/Row.java | 4 ++++ src/test/java/domain/ColumnTest.java | 9 +++++++++ src/test/java/domain/RowTest.java | 9 +++++++++ 4 files changed, 26 insertions(+) diff --git a/src/main/java/domain/Column.java b/src/main/java/domain/Column.java index efada677ee..02a52fe8de 100644 --- a/src/main/java/domain/Column.java +++ b/src/main/java/domain/Column.java @@ -1,6 +1,7 @@ package domain; public record Column(int value) { + private static final int COLUMN_MIN_SIZE = 0; private static final int COLUMN_MAX_SIZE = 8; public Column { @@ -8,6 +9,9 @@ public record Column(int value) { } private void validateColumn(int number) { + if (number < COLUMN_MIN_SIZE) { + throw new IllegalArgumentException("열의 최소 값은 " + COLUMN_MIN_SIZE + "입니다."); + } if (number > COLUMN_MAX_SIZE) { throw new IllegalArgumentException("열의 최대 값은 " + COLUMN_MAX_SIZE + "입니다."); } diff --git a/src/main/java/domain/Row.java b/src/main/java/domain/Row.java index f33b0a0cfa..f7d724c4af 100644 --- a/src/main/java/domain/Row.java +++ b/src/main/java/domain/Row.java @@ -1,6 +1,7 @@ package domain; public record Row(int value) { + private static final int ROW_MIN_SIZE = 0; private static final int ROW_MAX_SIZE = 9; public Row { @@ -8,6 +9,9 @@ public record Row(int value) { } private void validateRow(int value) { + if (value < ROW_MIN_SIZE) { + throw new IllegalArgumentException("행의 최소 값은 " + ROW_MIN_SIZE + "입니다."); + } if (value > ROW_MAX_SIZE) { throw new IllegalArgumentException("행의 최대 값은 " + ROW_MAX_SIZE + "입니다."); } diff --git a/src/test/java/domain/ColumnTest.java b/src/test/java/domain/ColumnTest.java index f97ccc59b3..a67a132d8a 100644 --- a/src/test/java/domain/ColumnTest.java +++ b/src/test/java/domain/ColumnTest.java @@ -21,6 +21,15 @@ class 생성 { @Nested class 예외 { + @Test + void 값이_최솟값보다_작으면_예외를_발행한다() { + int input = -1; + + assertThatThrownBy(() -> new Column(input)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("열의 최소 값은 0입니다."); + } + @Test void 값이_최댓값을_초과하면_예외를_발행한다() { int input = 19; diff --git a/src/test/java/domain/RowTest.java b/src/test/java/domain/RowTest.java index 0b3abe2dc8..f70e4ecd13 100644 --- a/src/test/java/domain/RowTest.java +++ b/src/test/java/domain/RowTest.java @@ -21,6 +21,15 @@ class 생성 { @Nested class 예외 { + @Test + void 값이_최솟값보다_작으면_예외를_발행한다() { + int input = -1; + + assertThatThrownBy(() -> new Row(input)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("행의 최소 값은 0입니다."); + } + @Test void 값이_최댓값을_초과하면_예외를_발행한다() { int input = 19; From bb1b301ffe8648b3e441e2fafbb78d70e8b1aa7d Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sat, 28 Mar 2026 16:22:17 +0900 Subject: [PATCH 78/82] =?UTF-8?q?refactor:=20Position=20=EC=A0=95=EC=A0=81?= =?UTF-8?q?=20=ED=8C=A9=ED=86=A0=EB=A6=AC=20=EC=BA=90=EC=8B=B1=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/domain/Position.java | 44 ++++++++++++++++++++++++-- src/test/java/domain/PositionTest.java | 37 ++++++++++++++++++++++ 2 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 src/test/java/domain/PositionTest.java diff --git a/src/main/java/domain/Position.java b/src/main/java/domain/Position.java index 98d439cbf4..439145f205 100644 --- a/src/main/java/domain/Position.java +++ b/src/main/java/domain/Position.java @@ -1,8 +1,16 @@ package domain; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; public class Position { + private static final int BOARD_MIN_INDEX = 0; + private static final int BOARD_MAX_ROW = 9; + private static final int BOARD_MAX_COLUMN = 8; + private static final int BOARD_COLUMN_SIZE = BOARD_MAX_COLUMN + 1; + private static final Map CACHE = createCache(); + private final Row row; private final Column column; @@ -17,8 +25,10 @@ public Position next(Direction direction) { return Position.of(nextRow, nextCol); } + public static Position of(int row, int column) { - return new Position(new Row(row), new Column(column)); + validateBoardIndex(row, column); + return CACHE.get(toCacheKey(row, column)); } public int row() { @@ -30,7 +40,8 @@ public int column() { } public boolean isInsideBoard() { - return row() >= 0 && row() <= 9 && column() >= 0 && column() <= 8; + return row() >= BOARD_MIN_INDEX && row() <= BOARD_MAX_ROW + && column() >= BOARD_MIN_INDEX && column() <= BOARD_MAX_COLUMN; } @Override @@ -52,4 +63,33 @@ public String toString() { return "(" + row() + "," + column() + ")"; } + private static Map createCache() { + final Map cache = new HashMap<>(); + for (int row = BOARD_MIN_INDEX; row <= BOARD_MAX_ROW; row++) { + for (int column = BOARD_MIN_INDEX; column <= BOARD_MAX_COLUMN; column++) { + cache.put(toCacheKey(row, column), new Position(new Row(row), new Column(column))); + } + } + return cache; + } + + private static int toCacheKey(int row, int column) { + return row * BOARD_COLUMN_SIZE + column; + } + + private static void validateBoardIndex(int row, int column) { + if (row < BOARD_MIN_INDEX) { + throw new IllegalArgumentException("행의 최소 값은 " + BOARD_MIN_INDEX + "입니다."); + } + if (row > BOARD_MAX_ROW) { + throw new IllegalArgumentException("행의 최대 값은 " + BOARD_MAX_ROW + "입니다."); + } + if (column < BOARD_MIN_INDEX) { + throw new IllegalArgumentException("열의 최소 값은 " + BOARD_MIN_INDEX + "입니다."); + } + if (column > BOARD_MAX_COLUMN) { + throw new IllegalArgumentException("열의 최대 값은 " + BOARD_MAX_COLUMN + "입니다."); + } + } + } diff --git a/src/test/java/domain/PositionTest.java b/src/test/java/domain/PositionTest.java new file mode 100644 index 0000000000..367cd6f81f --- /dev/null +++ b/src/test/java/domain/PositionTest.java @@ -0,0 +1,37 @@ +package domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class PositionTest { + + @Nested + class 생성 { + @Test + void 같은_좌표를_요청하면_캐시된_객체를_재사용한다() { + final Position first = Position.of(3, 4); + final Position second = Position.of(3, 4); + + assertThat(first).isSameAs(second); + } + } + + @Nested + class 예외 { + @Test + void 행이_범위를_벗어나면_예외를_발생한다() { + assertThatThrownBy(() -> Position.of(-1, 4)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("행의 최소 값은 0입니다."); + } + + @Test + void 열이_범위를_벗어나면_예외를_발생한다() { + assertThatThrownBy(() -> Position.of(4, 9)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("열의 최대 값은 8입니다."); + } + } +} From 15a6ddd4d716259bab0d691c96da3f6b84059332 Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sat, 28 Mar 2026 16:28:38 +0900 Subject: [PATCH 79/82] =?UTF-8?q?refactor:=20=EB=8F=84=EB=A9=94=EC=9D=B8?= =?UTF-8?q?=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EB=B6=84=EB=A5=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/Initializer.java | 10 ++++++---- src/main/java/Main.java | 2 ++ src/main/java/Runner.java | 14 ++++++++------ src/main/java/domain/{ => board}/Board.java | 9 +++++++-- src/main/java/domain/{ => board}/Column.java | 5 ++++- .../java/domain/{ => board}/Direction.java | 6 ++++-- src/main/java/domain/{ => board}/MovePath.java | 5 ++++- src/main/java/domain/{ => board}/Position.java | 5 ++++- src/main/java/domain/{ => board}/Route.java | 5 ++++- src/main/java/domain/{ => board}/Row.java | 5 ++++- .../java/domain/{ => game}/TurnManager.java | 17 +++++++++++------ src/main/java/domain/{ => piece}/Piece.java | 7 ++++++- .../java/domain/{ => piece}/PieceType.java | 5 ++++- .../java/domain/{ => piece}/TeamColor.java | 5 ++++- src/main/java/io/InputView.java | 4 +++- src/main/java/io/OutputView.java | 14 ++++++++------ .../formation/InitialFormationStrategy.java | 10 ++++++---- .../formation/InnerFormationStrategy.java | 10 ++++++---- .../formation/LeftFormationStrategy.java | 10 ++++++---- .../formation/OuterFormationStrategy.java | 10 ++++++---- .../formation/RightFormationStrategy.java | 10 ++++++---- .../java/strategy/move/CannonMoveStrategy.java | 14 ++++++++------ .../strategy/move/ElephantMoveStrategy.java | 8 +++++--- .../java/strategy/move/GuardMoveStrategy.java | 8 +++++--- .../java/strategy/move/HorseMoveStrategy.java | 8 +++++--- .../java/strategy/move/KingMoveStrategy.java | 8 +++++--- src/main/java/strategy/move/MoveStrategy.java | 14 ++++++++------ .../java/strategy/move/PawnMoveStrategy.java | 8 +++++--- .../java/strategy/move/RookMoveStrategy.java | 8 +++++--- src/test/java/InitializerTest.java | 10 ++++++---- .../java/domain/{ => board}/BoardTest.java | 18 ++++++++++++------ .../java/domain/{ => board}/ColumnTest.java | 5 ++++- .../java/domain/{ => board}/PositionTest.java | 5 ++++- src/test/java/domain/{ => board}/RowTest.java | 5 ++++- .../domain/{ => game}/TurnManagerTest.java | 6 +++++- .../java/domain/{ => piece}/PieceTest.java | 15 ++++++++++----- .../InitialFormationStrategyTest.java | 10 ++++++---- .../formation/InnerFormationStrategyTest.java | 10 ++++++---- .../formation/LeftFormationStrategyTest.java | 10 ++++++---- .../formation/OuterFormationStrategyTest.java | 10 ++++++---- .../formation/RightFormationStrategyTest.java | 10 ++++++---- .../strategy/move/CannonMoveStrategyTest.java | 16 +++++++++------- .../move/ElephantMoveStrategyTest.java | 16 +++++++++------- .../strategy/move/GuardMoveStrategyTest.java | 16 +++++++++------- .../strategy/move/HorseMoveStrategyTest.java | 16 +++++++++------- .../strategy/move/KingMoveStrategyTest.java | 16 +++++++++------- .../java/strategy/move/MoveStategyTest.java | 2 ++ .../strategy/move/PawnMoveStrategyTest.java | 16 +++++++++------- .../strategy/move/RookMoveStrategyTest.java | 16 +++++++++------- 49 files changed, 299 insertions(+), 173 deletions(-) rename src/main/java/domain/{ => board}/Board.java (94%) rename src/main/java/domain/{ => board}/Column.java (95%) rename src/main/java/domain/{ => board}/Direction.java (94%) rename src/main/java/domain/{ => board}/MovePath.java (75%) rename src/main/java/domain/{ => board}/Position.java (99%) rename src/main/java/domain/{ => board}/Route.java (82%) rename src/main/java/domain/{ => board}/Row.java (95%) rename src/main/java/domain/{ => game}/TurnManager.java (57%) rename src/main/java/domain/{ => piece}/Piece.java (96%) rename src/main/java/domain/{ => piece}/PieceType.java (80%) rename src/main/java/domain/{ => piece}/TeamColor.java (87%) rename src/test/java/domain/{ => board}/BoardTest.java (88%) rename src/test/java/domain/{ => board}/ColumnTest.java (97%) rename src/test/java/domain/{ => board}/PositionTest.java (97%) rename src/test/java/domain/{ => board}/RowTest.java (97%) rename src/test/java/domain/{ => game}/TurnManagerTest.java (93%) rename src/test/java/domain/{ => piece}/PieceTest.java (72%) diff --git a/src/main/java/Initializer.java b/src/main/java/Initializer.java index a1e72b0d7d..a34156e9aa 100644 --- a/src/main/java/Initializer.java +++ b/src/main/java/Initializer.java @@ -1,7 +1,7 @@ -import domain.Board; -import domain.Piece; -import domain.Position; -import domain.TeamColor; +import domain.board.Board; +import domain.piece.Piece; +import domain.board.Position; +import domain.piece.TeamColor; import java.util.HashMap; import java.util.Map; import strategy.formation.InitialFormationStrategy; @@ -23,3 +23,5 @@ public Board initialize() { return new Board(board); } } + + diff --git a/src/main/java/Main.java b/src/main/java/Main.java index f38d90dff8..f2a633be0f 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -4,3 +4,5 @@ public static void main(String[] args) { new Runner().run(); } } + + diff --git a/src/main/java/Runner.java b/src/main/java/Runner.java index e5d9397aad..a56e60e775 100644 --- a/src/main/java/Runner.java +++ b/src/main/java/Runner.java @@ -1,9 +1,9 @@ -import domain.Board; -import domain.Piece; -import domain.Position; -import domain.Route; -import domain.TeamColor; -import domain.TurnManager; +import domain.board.Board; +import domain.piece.Piece; +import domain.board.Position; +import domain.board.Route; +import domain.piece.TeamColor; +import domain.game.TurnManager; import io.InputView; import io.OutputView; import java.util.List; @@ -143,3 +143,5 @@ private Route getSelectedRoute(List routes, int routeChoice) { return routes.get(routeChoice - ZERO_BASE_INDEX_OFFSET); } } + + diff --git a/src/main/java/domain/Board.java b/src/main/java/domain/board/Board.java similarity index 94% rename from src/main/java/domain/Board.java rename to src/main/java/domain/board/Board.java index daf90c3383..a65c57f8d9 100644 --- a/src/main/java/domain/Board.java +++ b/src/main/java/domain/board/Board.java @@ -1,5 +1,7 @@ -package domain; +package domain.board; +import domain.piece.Piece; +import domain.piece.TeamColor; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -39,7 +41,7 @@ public List> findPiecesByTeam(TeamColor teamColor) { return pieces.entrySet().stream() .filter(entry -> entry.getValue().getTeamColor() == teamColor) .sorted((left, right) -> { - int rowCompare = Integer.compare(left.getKey().row(), right.getKey().row()); + final int rowCompare = Integer.compare(left.getKey().row(), right.getKey().row()); if (rowCompare != 0) { return rowCompare; } @@ -78,3 +80,6 @@ public void move(Piece piece, Position destination) { pieces.put(destination, piece); } } + + + diff --git a/src/main/java/domain/Column.java b/src/main/java/domain/board/Column.java similarity index 95% rename from src/main/java/domain/Column.java rename to src/main/java/domain/board/Column.java index 02a52fe8de..bc3dcfe8f7 100644 --- a/src/main/java/domain/Column.java +++ b/src/main/java/domain/board/Column.java @@ -1,4 +1,4 @@ -package domain; +package domain.board; public record Column(int value) { private static final int COLUMN_MIN_SIZE = 0; @@ -17,3 +17,6 @@ private void validateColumn(int number) { } } } + + + diff --git a/src/main/java/domain/Direction.java b/src/main/java/domain/board/Direction.java similarity index 94% rename from src/main/java/domain/Direction.java rename to src/main/java/domain/board/Direction.java index cf39c82c46..d7cd527d28 100644 --- a/src/main/java/domain/Direction.java +++ b/src/main/java/domain/board/Direction.java @@ -1,4 +1,4 @@ -package domain; +package domain.board; public enum Direction { NORTH(-1, 0), @@ -25,4 +25,6 @@ public int dRow() { public int dColumn() { return dColumn; } -} \ No newline at end of file +} + + diff --git a/src/main/java/domain/MovePath.java b/src/main/java/domain/board/MovePath.java similarity index 75% rename from src/main/java/domain/MovePath.java rename to src/main/java/domain/board/MovePath.java index 0a36f8c55d..6df40d5aad 100644 --- a/src/main/java/domain/MovePath.java +++ b/src/main/java/domain/board/MovePath.java @@ -1,6 +1,9 @@ -package domain; +package domain.board; import java.util.List; public record MovePath(List steps) {} + + + diff --git a/src/main/java/domain/Position.java b/src/main/java/domain/board/Position.java similarity index 99% rename from src/main/java/domain/Position.java rename to src/main/java/domain/board/Position.java index 439145f205..7fbaf591ec 100644 --- a/src/main/java/domain/Position.java +++ b/src/main/java/domain/board/Position.java @@ -1,4 +1,4 @@ -package domain; +package domain.board; import java.util.HashMap; import java.util.Map; @@ -93,3 +93,6 @@ private static void validateBoardIndex(int row, int column) { } } + + + diff --git a/src/main/java/domain/Route.java b/src/main/java/domain/board/Route.java similarity index 82% rename from src/main/java/domain/Route.java rename to src/main/java/domain/board/Route.java index 97bebe5ad4..22e5413b44 100644 --- a/src/main/java/domain/Route.java +++ b/src/main/java/domain/board/Route.java @@ -1,5 +1,8 @@ -package domain; +package domain.board; import java.util.List; public record Route(Position startPos, Position endPos, List intermeidateNodes) {} + + + diff --git a/src/main/java/domain/Row.java b/src/main/java/domain/board/Row.java similarity index 95% rename from src/main/java/domain/Row.java rename to src/main/java/domain/board/Row.java index f7d724c4af..21078c6ca9 100644 --- a/src/main/java/domain/Row.java +++ b/src/main/java/domain/board/Row.java @@ -1,4 +1,4 @@ -package domain; +package domain.board; public record Row(int value) { private static final int ROW_MIN_SIZE = 0; @@ -17,3 +17,6 @@ private void validateRow(int value) { } } } + + + diff --git a/src/main/java/domain/TurnManager.java b/src/main/java/domain/game/TurnManager.java similarity index 57% rename from src/main/java/domain/TurnManager.java rename to src/main/java/domain/game/TurnManager.java index 71474ff904..7b35d3415f 100644 --- a/src/main/java/domain/TurnManager.java +++ b/src/main/java/domain/game/TurnManager.java @@ -1,18 +1,20 @@ -package domain; +package domain.game; + +import domain.piece.TeamColor; public class TurnManager { - TeamColor teamColor; - int moveCount; + private TeamColor teamColor; + private int moveCount; - public TurnManager(){ + public TurnManager() { teamColor = TeamColor.CHO; moveCount = 0; } - public void progressTurn(){ + public void progressTurn() { moveCount += 1; - if(teamColor.equals(TeamColor.CHO)) { + if (teamColor.equals(TeamColor.CHO)) { teamColor = TeamColor.HAN; return; } @@ -23,3 +25,6 @@ public TeamColor getCurrentTurn() { return teamColor; } } + + + diff --git a/src/main/java/domain/Piece.java b/src/main/java/domain/piece/Piece.java similarity index 96% rename from src/main/java/domain/Piece.java rename to src/main/java/domain/piece/Piece.java index 7389990b89..0ee9f48a1f 100644 --- a/src/main/java/domain/Piece.java +++ b/src/main/java/domain/piece/Piece.java @@ -1,5 +1,7 @@ -package domain; +package domain.piece; +import domain.board.Position; +import domain.board.Route; import java.util.EnumMap; import java.util.List; import java.util.Map; @@ -63,3 +65,6 @@ private static Map createMoveStrategies() { return moveStrategies; } } + + + diff --git a/src/main/java/domain/PieceType.java b/src/main/java/domain/piece/PieceType.java similarity index 80% rename from src/main/java/domain/PieceType.java rename to src/main/java/domain/piece/PieceType.java index a3d9a0cad6..c3af68adec 100644 --- a/src/main/java/domain/PieceType.java +++ b/src/main/java/domain/piece/PieceType.java @@ -1,4 +1,4 @@ -package domain; +package domain.piece; public enum PieceType { CANNON, @@ -11,3 +11,6 @@ public enum PieceType { } + + + diff --git a/src/main/java/domain/TeamColor.java b/src/main/java/domain/piece/TeamColor.java similarity index 87% rename from src/main/java/domain/TeamColor.java rename to src/main/java/domain/piece/TeamColor.java index d75ec36e4c..5ef729d9e6 100644 --- a/src/main/java/domain/TeamColor.java +++ b/src/main/java/domain/piece/TeamColor.java @@ -1,4 +1,4 @@ -package domain; +package domain.piece; public enum TeamColor { CHO, @@ -11,3 +11,6 @@ public String displayName() { return "한"; } } + + + diff --git a/src/main/java/io/InputView.java b/src/main/java/io/InputView.java index 02f79f5038..e2c97abdad 100644 --- a/src/main/java/io/InputView.java +++ b/src/main/java/io/InputView.java @@ -1,6 +1,6 @@ package io; -import domain.TeamColor; +import domain.piece.TeamColor; import java.util.Scanner; public class InputView { @@ -34,3 +34,5 @@ public int readRouteChoice() { } } + + diff --git a/src/main/java/io/OutputView.java b/src/main/java/io/OutputView.java index f1af55c026..79534c3ff3 100644 --- a/src/main/java/io/OutputView.java +++ b/src/main/java/io/OutputView.java @@ -1,11 +1,11 @@ package io; -import domain.Board; -import domain.Piece; -import domain.PieceType; -import domain.Position; -import domain.Route; -import domain.TeamColor; +import domain.board.Board; +import domain.piece.Piece; +import domain.piece.PieceType; +import domain.board.Position; +import domain.board.Route; +import domain.piece.TeamColor; import java.util.EnumMap; import java.util.List; import java.util.Map; @@ -141,3 +141,5 @@ private static Map createPieceSymbols() { return pieceSymbols; } } + + diff --git a/src/main/java/strategy/formation/InitialFormationStrategy.java b/src/main/java/strategy/formation/InitialFormationStrategy.java index 0b0e1d6599..b5876c6edf 100644 --- a/src/main/java/strategy/formation/InitialFormationStrategy.java +++ b/src/main/java/strategy/formation/InitialFormationStrategy.java @@ -1,9 +1,9 @@ package strategy.formation; -import domain.Piece; -import domain.PieceType; -import domain.Position; -import domain.TeamColor; +import domain.piece.Piece; +import domain.piece.PieceType; +import domain.board.Position; +import domain.piece.TeamColor; import java.util.HashMap; import java.util.Map; @@ -73,3 +73,5 @@ private Map createFixedMap(TeamColor teamColor, int backRankRow return map; } } + + diff --git a/src/main/java/strategy/formation/InnerFormationStrategy.java b/src/main/java/strategy/formation/InnerFormationStrategy.java index 6776f2f425..18b42b0bd4 100644 --- a/src/main/java/strategy/formation/InnerFormationStrategy.java +++ b/src/main/java/strategy/formation/InnerFormationStrategy.java @@ -1,9 +1,9 @@ package strategy.formation; -import domain.Piece; -import domain.PieceType; -import domain.Position; -import domain.TeamColor; +import domain.piece.Piece; +import domain.piece.PieceType; +import domain.board.Position; +import domain.piece.TeamColor; import java.util.HashMap; import java.util.Map; @@ -30,3 +30,5 @@ private Map createFormation(TeamColor teamColor, int row) { return formation; } } + + diff --git a/src/main/java/strategy/formation/LeftFormationStrategy.java b/src/main/java/strategy/formation/LeftFormationStrategy.java index 9d3e44a739..f53931907f 100644 --- a/src/main/java/strategy/formation/LeftFormationStrategy.java +++ b/src/main/java/strategy/formation/LeftFormationStrategy.java @@ -1,9 +1,9 @@ package strategy.formation; -import domain.Piece; -import domain.PieceType; -import domain.Position; -import domain.TeamColor; +import domain.piece.Piece; +import domain.piece.PieceType; +import domain.board.Position; +import domain.piece.TeamColor; import java.util.HashMap; import java.util.Map; @@ -25,3 +25,5 @@ protected Map setupFormation(TeamColor teamColor) { return formation; } } + + diff --git a/src/main/java/strategy/formation/OuterFormationStrategy.java b/src/main/java/strategy/formation/OuterFormationStrategy.java index c5a884e713..ab70979bb8 100644 --- a/src/main/java/strategy/formation/OuterFormationStrategy.java +++ b/src/main/java/strategy/formation/OuterFormationStrategy.java @@ -1,9 +1,9 @@ package strategy.formation; -import domain.Piece; -import domain.PieceType; -import domain.Position; -import domain.TeamColor; +import domain.piece.Piece; +import domain.piece.PieceType; +import domain.board.Position; +import domain.piece.TeamColor; import java.util.HashMap; import java.util.Map; @@ -25,3 +25,5 @@ protected Map setupFormation(TeamColor teamColor) { return formation; } } + + diff --git a/src/main/java/strategy/formation/RightFormationStrategy.java b/src/main/java/strategy/formation/RightFormationStrategy.java index 8167c3be24..336036356a 100644 --- a/src/main/java/strategy/formation/RightFormationStrategy.java +++ b/src/main/java/strategy/formation/RightFormationStrategy.java @@ -1,9 +1,9 @@ package strategy.formation; -import domain.Piece; -import domain.PieceType; -import domain.Position; -import domain.TeamColor; +import domain.piece.Piece; +import domain.piece.PieceType; +import domain.board.Position; +import domain.piece.TeamColor; import java.util.HashMap; import java.util.Map; @@ -25,3 +25,5 @@ protected Map setupFormation(TeamColor teamColor) { return formation; } } + + diff --git a/src/main/java/strategy/move/CannonMoveStrategy.java b/src/main/java/strategy/move/CannonMoveStrategy.java index daed5f2275..6bef6ecef1 100644 --- a/src/main/java/strategy/move/CannonMoveStrategy.java +++ b/src/main/java/strategy/move/CannonMoveStrategy.java @@ -1,11 +1,11 @@ package strategy.move; -import domain.Direction; -import domain.MovePath; -import domain.Piece; -import domain.PieceType; -import domain.Route; -import domain.TeamColor; +import domain.board.Direction; +import domain.board.MovePath; +import domain.piece.Piece; +import domain.piece.PieceType; +import domain.board.Route; +import domain.piece.TeamColor; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -60,3 +60,5 @@ public boolean canMove(Route route, List blockingPieces, Optional return targetPiece.getTeamColor() != myTeam; } } + + diff --git a/src/main/java/strategy/move/ElephantMoveStrategy.java b/src/main/java/strategy/move/ElephantMoveStrategy.java index 1d4e8a5b70..20b10f6683 100644 --- a/src/main/java/strategy/move/ElephantMoveStrategy.java +++ b/src/main/java/strategy/move/ElephantMoveStrategy.java @@ -1,8 +1,8 @@ package strategy.move; -import domain.Direction; -import domain.MovePath; -import domain.TeamColor; +import domain.board.Direction; +import domain.board.MovePath; +import domain.piece.TeamColor; import java.util.List; public class ElephantMoveStrategy implements MoveStrategy { @@ -24,3 +24,5 @@ public List getPaths(TeamColor teamColor) { } } + + diff --git a/src/main/java/strategy/move/GuardMoveStrategy.java b/src/main/java/strategy/move/GuardMoveStrategy.java index c619d7975a..3ff3e132ee 100644 --- a/src/main/java/strategy/move/GuardMoveStrategy.java +++ b/src/main/java/strategy/move/GuardMoveStrategy.java @@ -1,8 +1,8 @@ package strategy.move; -import domain.Direction; -import domain.MovePath; -import domain.TeamColor; +import domain.board.Direction; +import domain.board.MovePath; +import domain.piece.TeamColor; import java.util.List; public class GuardMoveStrategy implements MoveStrategy { @@ -23,3 +23,5 @@ public List getPaths(TeamColor teamColor) { return PATHS; } } + + diff --git a/src/main/java/strategy/move/HorseMoveStrategy.java b/src/main/java/strategy/move/HorseMoveStrategy.java index 17652101f1..4640c9a276 100644 --- a/src/main/java/strategy/move/HorseMoveStrategy.java +++ b/src/main/java/strategy/move/HorseMoveStrategy.java @@ -1,8 +1,8 @@ package strategy.move; -import domain.Direction; -import domain.MovePath; -import domain.TeamColor; +import domain.board.Direction; +import domain.board.MovePath; +import domain.piece.TeamColor; import java.util.List; public class HorseMoveStrategy implements MoveStrategy { @@ -23,3 +23,5 @@ public List getPaths(TeamColor teamColor) { return PATHS; } } + + diff --git a/src/main/java/strategy/move/KingMoveStrategy.java b/src/main/java/strategy/move/KingMoveStrategy.java index d2a357914d..9b7c7c194a 100644 --- a/src/main/java/strategy/move/KingMoveStrategy.java +++ b/src/main/java/strategy/move/KingMoveStrategy.java @@ -1,8 +1,8 @@ package strategy.move; -import domain.Direction; -import domain.MovePath; -import domain.TeamColor; +import domain.board.Direction; +import domain.board.MovePath; +import domain.piece.TeamColor; import java.util.List; public class KingMoveStrategy implements MoveStrategy { @@ -23,3 +23,5 @@ public List getPaths(TeamColor teamColor) { return PATHS; } } + + diff --git a/src/main/java/strategy/move/MoveStrategy.java b/src/main/java/strategy/move/MoveStrategy.java index 2c90bd6c76..b62577e733 100644 --- a/src/main/java/strategy/move/MoveStrategy.java +++ b/src/main/java/strategy/move/MoveStrategy.java @@ -1,11 +1,11 @@ package strategy.move; -import domain.Direction; -import domain.MovePath; -import domain.Piece; -import domain.Position; -import domain.Route; -import domain.TeamColor; +import domain.board.Direction; +import domain.board.MovePath; +import domain.piece.Piece; +import domain.board.Position; +import domain.board.Route; +import domain.piece.TeamColor; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -65,3 +65,5 @@ default boolean canMove(Route route, List blockingPieces, Optional } } + + diff --git a/src/main/java/strategy/move/PawnMoveStrategy.java b/src/main/java/strategy/move/PawnMoveStrategy.java index 6fcd856989..dc7fe58e10 100644 --- a/src/main/java/strategy/move/PawnMoveStrategy.java +++ b/src/main/java/strategy/move/PawnMoveStrategy.java @@ -1,8 +1,8 @@ package strategy.move; -import domain.Direction; -import domain.MovePath; -import domain.TeamColor; +import domain.board.Direction; +import domain.board.MovePath; +import domain.piece.TeamColor; import java.util.List; public class PawnMoveStrategy implements MoveStrategy{ @@ -25,3 +25,5 @@ public List getPaths(TeamColor teamColor) { ); } } + + diff --git a/src/main/java/strategy/move/RookMoveStrategy.java b/src/main/java/strategy/move/RookMoveStrategy.java index 3d42b766c2..4cce138595 100644 --- a/src/main/java/strategy/move/RookMoveStrategy.java +++ b/src/main/java/strategy/move/RookMoveStrategy.java @@ -1,8 +1,8 @@ package strategy.move; -import domain.Direction; -import domain.MovePath; -import domain.TeamColor; +import domain.board.Direction; +import domain.board.MovePath; +import domain.piece.TeamColor; import java.util.ArrayList; import java.util.List; @@ -33,3 +33,5 @@ private void addStraightPaths(List paths, Direction direction) { } } + + diff --git a/src/test/java/InitializerTest.java b/src/test/java/InitializerTest.java index f69d38bb78..041bf4189d 100644 --- a/src/test/java/InitializerTest.java +++ b/src/test/java/InitializerTest.java @@ -1,8 +1,8 @@ -import domain.Board; -import domain.PieceType; -import domain.Position; +import domain.board.Board; +import domain.piece.PieceType; +import domain.board.Position; -import domain.TeamColor; +import domain.piece.TeamColor; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -88,3 +88,5 @@ class 기물목록 { } } } + + diff --git a/src/test/java/domain/BoardTest.java b/src/test/java/domain/board/BoardTest.java similarity index 88% rename from src/test/java/domain/BoardTest.java rename to src/test/java/domain/board/BoardTest.java index 85a8ca04e4..a11837bb71 100644 --- a/src/test/java/domain/BoardTest.java +++ b/src/test/java/domain/board/BoardTest.java @@ -1,5 +1,8 @@ -package domain; +package domain.board; +import domain.piece.Piece; +import domain.piece.PieceType; +import domain.piece.TeamColor; import java.util.Map; import java.util.Optional; import org.junit.jupiter.api.BeforeEach; @@ -82,8 +85,8 @@ class 위치조회 { class 이동 { @Test void 기물과_도착지를_받아_실제_이동을_반영한다() { - Piece movingPawn = Piece.of(TeamColor.CHO, PieceType.PAWN); - Board movableBoard = new Board(Map.of( + final Piece movingPawn = Piece.of(TeamColor.CHO, PieceType.PAWN); + final Board movableBoard = new Board(Map.of( Position.of(4, 4), movingPawn )); @@ -96,9 +99,9 @@ class 이동 { @Test void 현재_판_상태를_기준으로_기물의_이동_가능_경로를_반환한다() { - Piece movingPawn = Piece.of(TeamColor.CHO, PieceType.PAWN); - Piece allyPiece = Piece.of(TeamColor.CHO, PieceType.GUARD); - Board movableBoard = new Board(Map.of( + final Piece movingPawn = Piece.of(TeamColor.CHO, PieceType.PAWN); + final Piece allyPiece = Piece.of(TeamColor.CHO, PieceType.GUARD); + final Board movableBoard = new Board(Map.of( Position.of(4, 4), movingPawn, Position.of(4, 5), allyPiece )); @@ -109,3 +112,6 @@ class 이동 { } } } + + + diff --git a/src/test/java/domain/ColumnTest.java b/src/test/java/domain/board/ColumnTest.java similarity index 97% rename from src/test/java/domain/ColumnTest.java rename to src/test/java/domain/board/ColumnTest.java index a67a132d8a..df8ed79b10 100644 --- a/src/test/java/domain/ColumnTest.java +++ b/src/test/java/domain/board/ColumnTest.java @@ -1,4 +1,4 @@ -package domain; +package domain.board; import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -40,3 +40,6 @@ class 예외 { } } } + + + diff --git a/src/test/java/domain/PositionTest.java b/src/test/java/domain/board/PositionTest.java similarity index 97% rename from src/test/java/domain/PositionTest.java rename to src/test/java/domain/board/PositionTest.java index 367cd6f81f..5c312fb48b 100644 --- a/src/test/java/domain/PositionTest.java +++ b/src/test/java/domain/board/PositionTest.java @@ -1,4 +1,4 @@ -package domain; +package domain.board; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -35,3 +35,6 @@ class 예외 { } } } + + + diff --git a/src/test/java/domain/RowTest.java b/src/test/java/domain/board/RowTest.java similarity index 97% rename from src/test/java/domain/RowTest.java rename to src/test/java/domain/board/RowTest.java index f70e4ecd13..a96fc96c26 100644 --- a/src/test/java/domain/RowTest.java +++ b/src/test/java/domain/board/RowTest.java @@ -1,4 +1,4 @@ -package domain; +package domain.board; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; @@ -40,3 +40,6 @@ class 예외 { } } } + + + diff --git a/src/test/java/domain/TurnManagerTest.java b/src/test/java/domain/game/TurnManagerTest.java similarity index 93% rename from src/test/java/domain/TurnManagerTest.java rename to src/test/java/domain/game/TurnManagerTest.java index 7f8ac763e7..b9c0857ed9 100644 --- a/src/test/java/domain/TurnManagerTest.java +++ b/src/test/java/domain/game/TurnManagerTest.java @@ -1,5 +1,6 @@ -package domain; +package domain.game; +import domain.piece.TeamColor; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -31,3 +32,6 @@ class 턴진행 { } } } + + + diff --git a/src/test/java/domain/PieceTest.java b/src/test/java/domain/piece/PieceTest.java similarity index 72% rename from src/test/java/domain/PieceTest.java rename to src/test/java/domain/piece/PieceTest.java index 3414f0ac2f..2e15c27bc0 100644 --- a/src/test/java/domain/PieceTest.java +++ b/src/test/java/domain/piece/PieceTest.java @@ -1,5 +1,7 @@ -package domain; +package domain.piece; +import domain.board.Position; +import domain.board.Route; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.Nested; @@ -13,7 +15,7 @@ class PieceTest { class 전략위임 { @Test void 기물은_자기_전략으로_후보_경로를_생성한다() { - Piece piece = Piece.of(TeamColor.CHO, PieceType.PAWN); + final Piece piece = Piece.of(TeamColor.CHO, PieceType.PAWN); assertThat(piece.makeRoutes(Position.of(2, 3))).containsExactlyInAnyOrder( new Route(Position.of(2, 3), Position.of(1, 3), List.of()), @@ -24,10 +26,10 @@ class 전략위임 { @Test void 기물은_자기_전략으로_이동_가능_여부를_판단한다() { - Piece piece = Piece.of(TeamColor.CHO, PieceType.PAWN); - Route route = new Route(Position.of(2, 3), Position.of(1, 3), List.of()); + final Piece piece = Piece.of(TeamColor.CHO, PieceType.PAWN); + final Route route = new Route(Position.of(2, 3), Position.of(1, 3), List.of()); - boolean canMove = piece.canMove( + final boolean canMove = piece.canMove( route, List.of(), Optional.of(Piece.of(TeamColor.HAN, PieceType.HORSE)) @@ -37,3 +39,6 @@ class 전략위임 { } } } + + + diff --git a/src/test/java/strategy/formation/InitialFormationStrategyTest.java b/src/test/java/strategy/formation/InitialFormationStrategyTest.java index ad7c8b067d..8e99e2a69b 100644 --- a/src/test/java/strategy/formation/InitialFormationStrategyTest.java +++ b/src/test/java/strategy/formation/InitialFormationStrategyTest.java @@ -1,9 +1,9 @@ package strategy.formation; -import domain.Piece; -import domain.PieceType; -import domain.Position; -import domain.TeamColor; +import domain.piece.Piece; +import domain.piece.PieceType; +import domain.board.Position; +import domain.piece.TeamColor; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -68,3 +68,5 @@ protected Map setupFormation(TeamColor teamColor) { return Map.of(); } } + + diff --git a/src/test/java/strategy/formation/InnerFormationStrategyTest.java b/src/test/java/strategy/formation/InnerFormationStrategyTest.java index efdb98911b..7178d446ab 100644 --- a/src/test/java/strategy/formation/InnerFormationStrategyTest.java +++ b/src/test/java/strategy/formation/InnerFormationStrategyTest.java @@ -1,9 +1,9 @@ package strategy.formation; -import domain.Piece; -import domain.PieceType; -import domain.Position; -import domain.TeamColor; +import domain.piece.Piece; +import domain.piece.PieceType; +import domain.board.Position; +import domain.piece.TeamColor; import java.util.Map; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -50,3 +50,5 @@ class 초나라 { } } } + + diff --git a/src/test/java/strategy/formation/LeftFormationStrategyTest.java b/src/test/java/strategy/formation/LeftFormationStrategyTest.java index 3ba865d7e6..23ff4b3430 100644 --- a/src/test/java/strategy/formation/LeftFormationStrategyTest.java +++ b/src/test/java/strategy/formation/LeftFormationStrategyTest.java @@ -1,9 +1,9 @@ package strategy.formation; -import domain.Piece; -import domain.PieceType; -import domain.Position; -import domain.TeamColor; +import domain.piece.Piece; +import domain.piece.PieceType; +import domain.board.Position; +import domain.piece.TeamColor; import java.util.Map; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -50,3 +50,5 @@ class 초나라 { } } } + + diff --git a/src/test/java/strategy/formation/OuterFormationStrategyTest.java b/src/test/java/strategy/formation/OuterFormationStrategyTest.java index fc1adc7522..2f34e75264 100644 --- a/src/test/java/strategy/formation/OuterFormationStrategyTest.java +++ b/src/test/java/strategy/formation/OuterFormationStrategyTest.java @@ -1,9 +1,9 @@ package strategy.formation; -import domain.Piece; -import domain.PieceType; -import domain.Position; -import domain.TeamColor; +import domain.piece.Piece; +import domain.piece.PieceType; +import domain.board.Position; +import domain.piece.TeamColor; import java.util.Map; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -49,3 +49,5 @@ class 초나라 { } } } + + diff --git a/src/test/java/strategy/formation/RightFormationStrategyTest.java b/src/test/java/strategy/formation/RightFormationStrategyTest.java index 527f3f5e39..36d19e1f16 100644 --- a/src/test/java/strategy/formation/RightFormationStrategyTest.java +++ b/src/test/java/strategy/formation/RightFormationStrategyTest.java @@ -1,9 +1,9 @@ package strategy.formation; -import domain.Piece; -import domain.PieceType; -import domain.Position; -import domain.TeamColor; +import domain.piece.Piece; +import domain.piece.PieceType; +import domain.board.Position; +import domain.piece.TeamColor; import java.util.Map; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -50,3 +50,5 @@ class 초나라 { } } } + + diff --git a/src/test/java/strategy/move/CannonMoveStrategyTest.java b/src/test/java/strategy/move/CannonMoveStrategyTest.java index 44b3e8845e..a6a1ab0849 100644 --- a/src/test/java/strategy/move/CannonMoveStrategyTest.java +++ b/src/test/java/strategy/move/CannonMoveStrategyTest.java @@ -1,12 +1,12 @@ package strategy.move; -import domain.Direction; -import domain.MovePath; -import domain.Piece; -import domain.PieceType; -import domain.Position; -import domain.Route; -import domain.TeamColor; +import domain.board.Direction; +import domain.board.MovePath; +import domain.piece.Piece; +import domain.piece.PieceType; +import domain.board.Position; +import domain.board.Route; +import domain.piece.TeamColor; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.Nested; @@ -169,3 +169,5 @@ class 차단검사 { } } } + + diff --git a/src/test/java/strategy/move/ElephantMoveStrategyTest.java b/src/test/java/strategy/move/ElephantMoveStrategyTest.java index 9499b2754e..b897e50cb3 100644 --- a/src/test/java/strategy/move/ElephantMoveStrategyTest.java +++ b/src/test/java/strategy/move/ElephantMoveStrategyTest.java @@ -1,12 +1,12 @@ package strategy.move; -import domain.Direction; -import domain.MovePath; -import domain.Piece; -import domain.PieceType; -import domain.Position; -import domain.Route; -import domain.TeamColor; +import domain.board.Direction; +import domain.board.MovePath; +import domain.piece.Piece; +import domain.piece.PieceType; +import domain.board.Position; +import domain.board.Route; +import domain.piece.TeamColor; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.Nested; @@ -94,3 +94,5 @@ class 좌표생성 { } } } + + diff --git a/src/test/java/strategy/move/GuardMoveStrategyTest.java b/src/test/java/strategy/move/GuardMoveStrategyTest.java index 4acc1d16ae..6352c3581d 100644 --- a/src/test/java/strategy/move/GuardMoveStrategyTest.java +++ b/src/test/java/strategy/move/GuardMoveStrategyTest.java @@ -1,12 +1,12 @@ package strategy.move; -import domain.Direction; -import domain.MovePath; -import domain.Piece; -import domain.PieceType; -import domain.Position; -import domain.Route; -import domain.TeamColor; +import domain.board.Direction; +import domain.board.MovePath; +import domain.piece.Piece; +import domain.piece.PieceType; +import domain.board.Position; +import domain.board.Route; +import domain.piece.TeamColor; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.Nested; @@ -104,3 +104,5 @@ class 좌표생성 { } } } + + diff --git a/src/test/java/strategy/move/HorseMoveStrategyTest.java b/src/test/java/strategy/move/HorseMoveStrategyTest.java index 6ac7494f3a..cc6e4a1b55 100644 --- a/src/test/java/strategy/move/HorseMoveStrategyTest.java +++ b/src/test/java/strategy/move/HorseMoveStrategyTest.java @@ -1,12 +1,12 @@ package strategy.move; -import domain.Direction; -import domain.MovePath; -import domain.Piece; -import domain.PieceType; -import domain.Position; -import domain.Route; -import domain.TeamColor; +import domain.board.Direction; +import domain.board.MovePath; +import domain.piece.Piece; +import domain.piece.PieceType; +import domain.board.Position; +import domain.board.Route; +import domain.piece.TeamColor; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.Nested; @@ -104,3 +104,5 @@ class 좌표생성 { } } } + + diff --git a/src/test/java/strategy/move/KingMoveStrategyTest.java b/src/test/java/strategy/move/KingMoveStrategyTest.java index fcc12cf6a9..9649a0c369 100644 --- a/src/test/java/strategy/move/KingMoveStrategyTest.java +++ b/src/test/java/strategy/move/KingMoveStrategyTest.java @@ -1,12 +1,12 @@ package strategy.move; -import domain.Direction; -import domain.MovePath; -import domain.Piece; -import domain.PieceType; -import domain.Position; -import domain.Route; -import domain.TeamColor; +import domain.board.Direction; +import domain.board.MovePath; +import domain.piece.Piece; +import domain.piece.PieceType; +import domain.board.Position; +import domain.board.Route; +import domain.piece.TeamColor; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.Nested; @@ -104,3 +104,5 @@ class 좌표생성 { } } } + + diff --git a/src/test/java/strategy/move/MoveStategyTest.java b/src/test/java/strategy/move/MoveStategyTest.java index 9bbc2d251e..e271012d0a 100644 --- a/src/test/java/strategy/move/MoveStategyTest.java +++ b/src/test/java/strategy/move/MoveStategyTest.java @@ -6,3 +6,5 @@ public class MoveStategyTest { } + + diff --git a/src/test/java/strategy/move/PawnMoveStrategyTest.java b/src/test/java/strategy/move/PawnMoveStrategyTest.java index 13037f2894..ba16694d6b 100644 --- a/src/test/java/strategy/move/PawnMoveStrategyTest.java +++ b/src/test/java/strategy/move/PawnMoveStrategyTest.java @@ -1,12 +1,12 @@ package strategy.move; -import domain.Direction; -import domain.MovePath; -import domain.Piece; -import domain.PieceType; -import domain.Position; -import domain.Route; -import domain.TeamColor; +import domain.board.Direction; +import domain.board.MovePath; +import domain.piece.Piece; +import domain.piece.PieceType; +import domain.board.Position; +import domain.board.Route; +import domain.piece.TeamColor; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.BeforeEach; @@ -104,3 +104,5 @@ class 차단검사 { } } } + + diff --git a/src/test/java/strategy/move/RookMoveStrategyTest.java b/src/test/java/strategy/move/RookMoveStrategyTest.java index 3d2cfd22e3..32ed858879 100644 --- a/src/test/java/strategy/move/RookMoveStrategyTest.java +++ b/src/test/java/strategy/move/RookMoveStrategyTest.java @@ -1,12 +1,12 @@ package strategy.move; -import domain.Direction; -import domain.MovePath; -import domain.Piece; -import domain.PieceType; -import domain.Position; -import domain.Route; -import domain.TeamColor; +import domain.board.Direction; +import domain.board.MovePath; +import domain.piece.Piece; +import domain.piece.PieceType; +import domain.board.Position; +import domain.board.Route; +import domain.piece.TeamColor; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.Nested; @@ -95,3 +95,5 @@ class 차단검사 { } } } + + From c9ceaae6961a5175642e3c4cd184e2bd5d7776cb Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sun, 29 Mar 2026 17:46:35 +0900 Subject: [PATCH 80/82] =?UTF-8?q?refactor:=20=EB=84=A4=EC=9D=B4=EB=B0=8D?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?=EC=84=A4=EB=AA=85=20README=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + README.md | 40 +++++ src/main/java/Initializer.java | 27 ---- src/main/java/Main.java | 2 +- src/main/java/Runner.java | 147 ------------------ src/main/java/domain/board/Board.java | 2 +- src/main/java/domain/board/Route.java | 2 +- src/main/java/domain/game/TurnManager.java | 14 +- .../formation/InitialFormationStrategy.java | 6 +- .../formation/InnerFormationStrategy.java | 2 +- .../formation/LeftFormationStrategy.java | 2 +- .../formation/OuterFormationStrategy.java | 2 +- .../formation/RightFormationStrategy.java | 2 +- src/test/java/InitializerTest.java | 92 ----------- .../java/domain/game/TurnManagerTest.java | 2 +- .../InitialFormationStrategyTest.java | 6 +- .../formation/InnerFormationStrategyTest.java | 4 +- .../formation/LeftFormationStrategyTest.java | 4 +- .../formation/OuterFormationStrategyTest.java | 4 +- .../formation/RightFormationStrategyTest.java | 4 +- .../java/strategy/move/MoveStategyTest.java | 10 -- 21 files changed, 70 insertions(+), 305 deletions(-) delete mode 100644 src/main/java/Initializer.java delete mode 100644 src/main/java/Runner.java delete mode 100644 src/test/java/InitializerTest.java delete mode 100644 src/test/java/strategy/move/MoveStategyTest.java diff --git a/.gitignore b/.gitignore index c0b28e6ab2..3fd3e9ed7c 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ out/ ### VS Code ### .vscode/ +docs/record_memory.md diff --git a/README.md b/README.md index ef251ff6c2..7e3f380d02 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,46 @@ +### 주요 도메인 객체 설명 + +- `Board` + - 현재 장기판 상태를 관리하는 중심 객체 + - `Map`를 사용해 특정 위치의 기물 조회, 특정 기물의 현재 위치 조회, 이동 가능 경로 검증, 실제 이동 반영을 담당 + - 장기판의 "현재 상태"와 그 상태를 기준으로 한 판정을 한곳에 모으기 위해 별도 객체로 두었다. +- `Position` + - 장기판 위 한 칸의 위치를 표현 + - 유효한 행(Row)과 열(Column) 범위를 검증하는 값 객체로 사용 + - 보드의 거의 모든 규칙이 위치를 기준으로 동작하므로, 좌표를 원시값으로 흩뿌리지 않기 위해 분리했다. +- `Route` + - 기물의 실제 이동 경로를 나타낸다. + - 시작 위치, 도착 위치, 그리고 중간에 지나가는 칸들을 함께 가진다. + - 장기에서는 "어디로 가는가", "중간에 무엇을 지나가는가" 두 가지 모두 중요하므로, 도착지만 표현하는 대신 경로 전체를 표현하는 정보를 묶어서 객체로 다룬다. +- `MovePath` + - 기물이 따르는 이동 규칙 템플릿 + - ex. 마와 상처럼 여러 단계 방향 조합으로 움직이는 기물의 규칙을 표현하는 데 사용 + - 실제 장기판 좌표가 계산된 결과는 `Route`, 규칙 자체는 `MovePath`로 나누어 규칙 정의와 실행 결과를 분리 +- `Piece` + - 장기 기물 하나를 의미 + - 자신의 진영(`TeamColor`), 종류(`PieceType`), 이동 규칙(`MoveStrategy`)을 함께 가진다. + - 기물마다 이동 방식이 다르기 때문에, 기물 종류와 전략을 연결하는 축으로 두었다. +- `PieceType`, `TeamColor` + - 기물의 종류와 진영을 표현하는 분류 체계 + - 문자열 비교나 매직 넘버 대신 명확한 도메인 값으로 다루기 위해 분리 +- `MoveStrategy` + - 기물별 이동 규칙을 추상화한 전략 인터페이스 + - 차, 포, 마, 상, 왕, 사, 졸이 서로 다른 이동 규칙을 가지므로, 조건문을 한곳에 몰아넣지 않고 전략 객체로 분리 +- `InitialFormationStrategy` + - 게임 시작 시 초/한의 상차림 규칙을 표현하는 전략 + - 안상, 바깥상, 좌상, 우상처럼 초기 배치 변형이 존재하므로, 초기 세팅 규칙을 독립된 전략으로 분리 +- `BoardInitializer` + - 선택된 상차림 전략을 받아 초기 장기판 상태를 조립 + - 초기 기물 생성과 보드 생성 과정을 게임 진행 객체와 분리해, 시작 세팅 책임을 독립시켰다. +- `TurnManager` + - 현재 턴의 진영 정보 저장 및 턴 전환만 관리하는 객체 +- `GameRunner` + - 입력, 출력, 초기 세팅, 턴 진행을 연결해 실제 게임 루프를 실행 + - 도메인 규칙 자체를 담기보다, 여러 도메인 객체를 조합해 사용자와 상호작용하는 흐름을 담당 + ### 사이클1 구현 내용 - [x] [기능구현] 게임에서 사용할 분류 체계 정의 diff --git a/src/main/java/Initializer.java b/src/main/java/Initializer.java deleted file mode 100644 index a34156e9aa..0000000000 --- a/src/main/java/Initializer.java +++ /dev/null @@ -1,27 +0,0 @@ -import domain.board.Board; -import domain.piece.Piece; -import domain.board.Position; -import domain.piece.TeamColor; -import java.util.HashMap; -import java.util.Map; -import strategy.formation.InitialFormationStrategy; - -public class Initializer { - - private final InitialFormationStrategy choStrategy; - private final InitialFormationStrategy hanStrategy; - - public Initializer(InitialFormationStrategy choStrategy, InitialFormationStrategy hanStrategy) { - this.choStrategy = choStrategy; - this.hanStrategy = hanStrategy; - } - - public Board initialize() { - final Map board = new HashMap<>(); - board.putAll(choStrategy.setUpPieces(TeamColor.CHO)); - board.putAll(hanStrategy.setUpPieces(TeamColor.HAN)); - return new Board(board); - } -} - - diff --git a/src/main/java/Main.java b/src/main/java/Main.java index f2a633be0f..41792dcbdf 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,7 +1,7 @@ public class Main { public static void main(String[] args) { - new Runner().run(); + new GameRunner().run(); } } diff --git a/src/main/java/Runner.java b/src/main/java/Runner.java deleted file mode 100644 index a56e60e775..0000000000 --- a/src/main/java/Runner.java +++ /dev/null @@ -1,147 +0,0 @@ -import domain.board.Board; -import domain.piece.Piece; -import domain.board.Position; -import domain.board.Route; -import domain.piece.TeamColor; -import domain.game.TurnManager; -import io.InputView; -import io.OutputView; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import strategy.formation.InitialFormationStrategy; -import strategy.formation.InnerFormationStrategy; -import strategy.formation.LeftFormationStrategy; -import strategy.formation.OuterFormationStrategy; -import strategy.formation.RightFormationStrategy; - -public class Runner { - private static final int FIRST_OPTION_NUMBER = 1; - private static final int BACK_OPTION_NUMBER = 0; - private static final int ZERO_BASE_INDEX_OFFSET = 1; - private static final List FORMATIONS = List.of( - new InnerFormationStrategy(), - new OuterFormationStrategy(), - new LeftFormationStrategy(), - new RightFormationStrategy() - ); - - private final InputView inputView; - private final OutputView outputView; - private final TurnManager turnManager; - - public Runner() { - this(new InputView(), new OutputView(), new TurnManager()); - } - - public Runner(InputView inputView, OutputView outputView, TurnManager turnManager) { - this.inputView = inputView; - this.outputView = outputView; - this.turnManager = turnManager; - } - - public void run() { - outputView.printGameStart(); - - InitialFormationStrategy choStrategy = chooseFormationStrategy(TeamColor.CHO); - InitialFormationStrategy hanStrategy = chooseFormationStrategy(TeamColor.HAN); - - Initializer initializer = new Initializer(choStrategy, hanStrategy); - Board board = initializer.initialize(); - - outputView.printBoard(board); - - while (true) { - playTurn(board); - } - } - - private InitialFormationStrategy chooseFormationStrategy(TeamColor teamColor) { - while (true) { - outputView.printFormationSelectionPrompt(teamColor); - try { - return createFormationStrategy(inputView.readFormationChoice(teamColor)); - } catch (RuntimeException exception) { - outputView.printError("상차림 입력이 올바르지 않습니다."); - } - } - } - - private void playTurn(Board board) { - final TeamColor currentTurn = turnManager.getCurrentTurn(); - outputView.printCurrentTurn(currentTurn); - outputView.printBoard(board); - - while (true) { - try { - final Piece selectedPiece = choosePiece(board, currentTurn); - final Optional selectedRoute = chooseRoute(board, selectedPiece); - if (selectedRoute.isEmpty()) { - continue; - } - - final Position destination = selectedRoute.get().endPos(); - board.move(selectedPiece, destination); - outputView.printMoveResult(selectedPiece, destination); - turnManager.progressTurn(); - return; - } catch (RuntimeException exception) { - outputView.printError(exception.getMessage()); - } - } - } - - private InitialFormationStrategy createFormationStrategy(int choice) { - validateFormationChoice(choice); - return FORMATIONS.get(choice - ZERO_BASE_INDEX_OFFSET); - } - - private void validateFormationChoice(int choice) { - if (choice >= FIRST_OPTION_NUMBER && choice <= FORMATIONS.size()) { - return; - } - throw new IllegalArgumentException("상차림 번호는 1~4 사이여야 합니다."); - } - - private Piece choosePiece(Board board, TeamColor currentTurn) { - List> pieces = board.findPiecesByTeam(currentTurn); - outputView.printPieceOptions(pieces); - - final int pieceChoice = inputView.readPieceChoice(currentTurn); - return getSelectedPiece(pieces, pieceChoice); - } - - private Optional chooseRoute(Board board, Piece selectedPiece) { - final List routes = board.findMovableRoutes(selectedPiece); - validateMovableRoutes(routes); - outputView.printRouteOptions(routes); - - final int routeChoice = inputView.readRouteChoice(); - if (routeChoice == BACK_OPTION_NUMBER) { - return Optional.empty(); - } - return Optional.of(getSelectedRoute(routes, routeChoice)); - } - - private void validateMovableRoutes(List routes) { - if (routes.isEmpty()) { - throw new IllegalArgumentException("선택한 기물은 이동 가능한 경로가 없습니다."); - } - } - - private Piece getSelectedPiece(List> pieces, int pieceChoice) { - if (pieceChoice < FIRST_OPTION_NUMBER || pieceChoice > pieces.size()) { - throw new IllegalArgumentException("기물 번호가 범위를 벗어났습니다."); - } - return pieces.get(pieceChoice - ZERO_BASE_INDEX_OFFSET).getValue(); - } - - private Route getSelectedRoute(List routes, int routeChoice) { - if (routeChoice < FIRST_OPTION_NUMBER || routeChoice > routes.size()) { - throw new IllegalArgumentException("경로 번호가 범위를 벗어났습니다."); - } - return routes.get(routeChoice - ZERO_BASE_INDEX_OFFSET); - } -} - - diff --git a/src/main/java/domain/board/Board.java b/src/main/java/domain/board/Board.java index a65c57f8d9..a266499544 100644 --- a/src/main/java/domain/board/Board.java +++ b/src/main/java/domain/board/Board.java @@ -16,7 +16,7 @@ public Board(Map pieces) { } public List getBlockingPieces(Route route) { - return route.intermeidateNodes().stream() + return route.intermediatePositions().stream() .map(this::findPiece) .flatMap(Optional::stream) .toList(); diff --git a/src/main/java/domain/board/Route.java b/src/main/java/domain/board/Route.java index 22e5413b44..84e7d32576 100644 --- a/src/main/java/domain/board/Route.java +++ b/src/main/java/domain/board/Route.java @@ -2,7 +2,7 @@ import java.util.List; -public record Route(Position startPos, Position endPos, List intermeidateNodes) {} +public record Route(Position startPos, Position endPos, List intermediatePositions) {} diff --git a/src/main/java/domain/game/TurnManager.java b/src/main/java/domain/game/TurnManager.java index 7b35d3415f..5847d5be39 100644 --- a/src/main/java/domain/game/TurnManager.java +++ b/src/main/java/domain/game/TurnManager.java @@ -4,25 +4,25 @@ public class TurnManager { - private TeamColor teamColor; + private TeamColor currentTurn; private int moveCount; public TurnManager() { - teamColor = TeamColor.CHO; + currentTurn = TeamColor.CHO; moveCount = 0; } - public void progressTurn() { + public void advanceTurn() { moveCount += 1; - if (teamColor.equals(TeamColor.CHO)) { - teamColor = TeamColor.HAN; + if (currentTurn.equals(TeamColor.CHO)) { + currentTurn = TeamColor.HAN; return; } - teamColor = TeamColor.CHO; + currentTurn = TeamColor.CHO; } public TeamColor getCurrentTurn() { - return teamColor; + return currentTurn; } } diff --git a/src/main/java/strategy/formation/InitialFormationStrategy.java b/src/main/java/strategy/formation/InitialFormationStrategy.java index b5876c6edf..ce73a448f5 100644 --- a/src/main/java/strategy/formation/InitialFormationStrategy.java +++ b/src/main/java/strategy/formation/InitialFormationStrategy.java @@ -25,8 +25,8 @@ public abstract class InitialFormationStrategy { private static final int RIGHT_EDGE_COLUMN = 8; private static final int PAWN_COLUMN_INTERVAL = 2; - public final Map setUpPieces(TeamColor teamColor) { - final Map formationPieces = setupFormation(teamColor); + public final Map createInitialPieces(TeamColor teamColor) { + final Map formationPieces = createFormationPieces(teamColor); final Map fixedPieces = placeFixedPieces(teamColor); final Map allPieces = new HashMap<>(); @@ -36,7 +36,7 @@ public final Map setUpPieces(TeamColor teamColor) { return allPieces; } - protected abstract Map setupFormation(TeamColor teamColor); + protected abstract Map createFormationPieces(TeamColor teamColor); protected final int findBackRankRow(TeamColor teamColor) { if (teamColor == TeamColor.CHO) { diff --git a/src/main/java/strategy/formation/InnerFormationStrategy.java b/src/main/java/strategy/formation/InnerFormationStrategy.java index 18b42b0bd4..945739fff7 100644 --- a/src/main/java/strategy/formation/InnerFormationStrategy.java +++ b/src/main/java/strategy/formation/InnerFormationStrategy.java @@ -14,7 +14,7 @@ public class InnerFormationStrategy extends InitialFormationStrategy { private static final int RIGHT_HORSE_COLUMN = 7; @Override - protected Map setupFormation(TeamColor teamColor) { + protected Map createFormationPieces(TeamColor teamColor) { if (teamColor.equals(TeamColor.CHO)) { return createFormation(teamColor, CHO_BACK_RANK_ROW); } diff --git a/src/main/java/strategy/formation/LeftFormationStrategy.java b/src/main/java/strategy/formation/LeftFormationStrategy.java index f53931907f..9355be71f7 100644 --- a/src/main/java/strategy/formation/LeftFormationStrategy.java +++ b/src/main/java/strategy/formation/LeftFormationStrategy.java @@ -14,7 +14,7 @@ public class LeftFormationStrategy extends InitialFormationStrategy { private static final int RIGHT_ELEPHANT_COLUMN = 7; @Override - protected Map setupFormation(TeamColor teamColor) { + protected Map createFormationPieces(TeamColor teamColor) { final Map formation = new HashMap<>(); final int row = findBackRankRow(teamColor); diff --git a/src/main/java/strategy/formation/OuterFormationStrategy.java b/src/main/java/strategy/formation/OuterFormationStrategy.java index ab70979bb8..7dc5d1207d 100644 --- a/src/main/java/strategy/formation/OuterFormationStrategy.java +++ b/src/main/java/strategy/formation/OuterFormationStrategy.java @@ -14,7 +14,7 @@ public class OuterFormationStrategy extends InitialFormationStrategy { private static final int RIGHT_ELEPHANT_COLUMN = 7; @Override - protected Map setupFormation(TeamColor teamColor) { + protected Map createFormationPieces(TeamColor teamColor) { final Map formation = new HashMap<>(); final int row = findBackRankRow(teamColor); diff --git a/src/main/java/strategy/formation/RightFormationStrategy.java b/src/main/java/strategy/formation/RightFormationStrategy.java index 336036356a..8e672a5e42 100644 --- a/src/main/java/strategy/formation/RightFormationStrategy.java +++ b/src/main/java/strategy/formation/RightFormationStrategy.java @@ -14,7 +14,7 @@ public class RightFormationStrategy extends InitialFormationStrategy { private static final int RIGHT_HORSE_COLUMN = 7; @Override - protected Map setupFormation(TeamColor teamColor) { + protected Map createFormationPieces(TeamColor teamColor) { final Map formation = new HashMap<>(); final int row = findBackRankRow(teamColor); diff --git a/src/test/java/InitializerTest.java b/src/test/java/InitializerTest.java deleted file mode 100644 index 041bf4189d..0000000000 --- a/src/test/java/InitializerTest.java +++ /dev/null @@ -1,92 +0,0 @@ -import domain.board.Board; -import domain.piece.PieceType; -import domain.board.Position; - -import domain.piece.TeamColor; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - - - -import static org.assertj.core.api.Assertions.assertThat; -import strategy.formation.InitialFormationStrategy; -import strategy.formation.InnerFormationStrategy; - -class InitializerTest { - - InitialFormationStrategy choStrategy; - InitialFormationStrategy hanStrategy; - Board board; - - @BeforeEach - public void setUp(){ - choStrategy = new InnerFormationStrategy(); - hanStrategy = new InnerFormationStrategy(); - Initializer initializer = new Initializer(choStrategy, hanStrategy); - board = initializer.initialize(); - } - - - @Nested - class 초기화 { - @Test - void 초나라_한나라_전략을_주입받아_총_32개의_기물이_세팅된_초기_장기판을_반환한다() { - assertThat(board.findPiecesByTeam(TeamColor.CHO)).hasSize(16); - assertThat(board.findPiecesByTeam(TeamColor.HAN)).hasSize(16); - assertThat(board.findPiece(Position.of(8, 4))).get().extracting("pieceType").isEqualTo(PieceType.KING); - assertThat(board.findPiece(Position.of(0, 2))).get().extracting("pieceType").isEqualTo(PieceType.ELEPHANT); - } - } - - @Nested - class 기물목록 { - @Test - void 초나라_기물_리스트를_생성한다() { - assertThat(board.findPiecesByTeam(TeamColor.CHO)).hasSize(16); - assertThat( - board.findPiecesByTeam(TeamColor.CHO).stream() - .map(entry -> entry.getValue()) - .filter(p -> p.getPieceType() == PieceType.ELEPHANT) - ).hasSize(2); - - assertThat( - board.findPiecesByTeam(TeamColor.CHO).stream() - .map(entry -> entry.getValue()) - .filter(p -> p.getPieceType() == PieceType.HORSE) - ).hasSize(2); - - assertThat( - board.findPiecesByTeam(TeamColor.CHO).stream() - .map(entry -> entry.getValue()) - .filter(p -> p.getPieceType() == PieceType.CANNON) - ).hasSize(2); - - assertThat( - board.findPiecesByTeam(TeamColor.CHO).stream() - .map(entry -> entry.getValue()) - .filter(p -> p.getPieceType() == PieceType.ROOK) - ).hasSize(2); - - assertThat( - board.findPiecesByTeam(TeamColor.CHO).stream() - .map(entry -> entry.getValue()) - .filter(p -> p.getPieceType() == PieceType.GUARD) - ).hasSize(2); - - assertThat( - board.findPiecesByTeam(TeamColor.CHO).stream() - .map(entry -> entry.getValue()) - .filter(p -> p.getPieceType() == PieceType.PAWN) - ).hasSize(5); - - assertThat( - board.findPiecesByTeam(TeamColor.CHO).stream() - .map(entry -> entry.getValue()) - .filter(p -> p.getPieceType() == PieceType.KING) - ).hasSize(1); - } - } -} - - diff --git a/src/test/java/domain/game/TurnManagerTest.java b/src/test/java/domain/game/TurnManagerTest.java index b9c0857ed9..65704d906e 100644 --- a/src/test/java/domain/game/TurnManagerTest.java +++ b/src/test/java/domain/game/TurnManagerTest.java @@ -27,7 +27,7 @@ class 현재턴 { class 턴진행 { @Test public void 턴이_바뀌면_반대팀이_현재_턴이_된다() { - turnManager.progressTurn(); + turnManager.advanceTurn(); assertThat(turnManager.getCurrentTurn()).isEqualTo(TeamColor.HAN); } } diff --git a/src/test/java/strategy/formation/InitialFormationStrategyTest.java b/src/test/java/strategy/formation/InitialFormationStrategyTest.java index 8e99e2a69b..f1ae92b38b 100644 --- a/src/test/java/strategy/formation/InitialFormationStrategyTest.java +++ b/src/test/java/strategy/formation/InitialFormationStrategyTest.java @@ -25,7 +25,7 @@ void setUp() { class 한나라 { @Test void 고정_기물들이_올바른_위치에_배치된다() { - Map result = strategy.setUpPieces(TeamColor.HAN); + Map result = strategy.createInitialPieces(TeamColor.HAN); assertThat(result).hasSize(12); assertThat(result.get(Position.of(0, 0)).getPieceType()).isEqualTo(PieceType.ROOK); @@ -45,7 +45,7 @@ class 한나라 { class 초나라 { @Test void 고정_기물들이_올바른_위치에_배치된다() { - Map result = strategy.setUpPieces(TeamColor.CHO); + Map result = strategy.createInitialPieces(TeamColor.CHO); assertThat(result).hasSize(12); assertThat(result.get(Position.of(9, 0)).getPieceType()).isEqualTo(PieceType.ROOK); @@ -64,7 +64,7 @@ class 초나라 { class TestStrategy extends InitialFormationStrategy { @Override - protected Map setupFormation(TeamColor teamColor) { + protected Map createFormationPieces(TeamColor teamColor) { return Map.of(); } } diff --git a/src/test/java/strategy/formation/InnerFormationStrategyTest.java b/src/test/java/strategy/formation/InnerFormationStrategyTest.java index 7178d446ab..5dfbd1073f 100644 --- a/src/test/java/strategy/formation/InnerFormationStrategyTest.java +++ b/src/test/java/strategy/formation/InnerFormationStrategyTest.java @@ -24,7 +24,7 @@ public void setUp() { class 한나라 { @Test public void 안상차림일_때_마와_상의_좌표가_올바르다() { - Map formation = initialFormationStrategy.setUpPieces(TeamColor.HAN); + Map formation = initialFormationStrategy.createInitialPieces(TeamColor.HAN); assertThat(formation.size()).isEqualTo(16); assertThat(formation.get(Position.of(0, 2)).getPieceType()).isEqualTo(PieceType.ELEPHANT); @@ -39,7 +39,7 @@ class 한나라 { class 초나라 { @Test public void 안상차림일_때_마와_상의_좌표가_올바르다() { - Map formation = initialFormationStrategy.setUpPieces(TeamColor.CHO); + Map formation = initialFormationStrategy.createInitialPieces(TeamColor.CHO); assertThat(formation.size()).isEqualTo(16); assertThat(formation.get(Position.of(9, 2)).getPieceType()).isEqualTo(PieceType.ELEPHANT); diff --git a/src/test/java/strategy/formation/LeftFormationStrategyTest.java b/src/test/java/strategy/formation/LeftFormationStrategyTest.java index 23ff4b3430..c090903420 100644 --- a/src/test/java/strategy/formation/LeftFormationStrategyTest.java +++ b/src/test/java/strategy/formation/LeftFormationStrategyTest.java @@ -24,7 +24,7 @@ public void setUp() { class 한나라 { @Test public void 좌상차림일_때_마와_상의_좌표가_올바르다() { - Map formation = initialFormationStrategy.setUpPieces(TeamColor.HAN); + Map formation = initialFormationStrategy.createInitialPieces(TeamColor.HAN); assertThat(formation.size()).isEqualTo(16); assertThat(formation.get(Position.of(0, 1)).getPieceType()).isEqualTo(PieceType.HORSE); @@ -39,7 +39,7 @@ class 한나라 { class 초나라 { @Test public void 좌상차림일_때_마와_상의_좌표가_올바르다() { - Map formation = initialFormationStrategy.setUpPieces(TeamColor.CHO); + Map formation = initialFormationStrategy.createInitialPieces(TeamColor.CHO); assertThat(formation.size()).isEqualTo(16); assertThat(formation.get(Position.of(9, 1)).getPieceType()).isEqualTo(PieceType.HORSE); diff --git a/src/test/java/strategy/formation/OuterFormationStrategyTest.java b/src/test/java/strategy/formation/OuterFormationStrategyTest.java index 2f34e75264..b4b7c450f0 100644 --- a/src/test/java/strategy/formation/OuterFormationStrategyTest.java +++ b/src/test/java/strategy/formation/OuterFormationStrategyTest.java @@ -23,7 +23,7 @@ public void setUp() { class 한나라 { @Test public void 바깥상차림일_때_마와_상의_좌표가_올바르다() { - Map formation = initialFormationStrategy.setUpPieces(TeamColor.HAN); + Map formation = initialFormationStrategy.createInitialPieces(TeamColor.HAN); assertThat(formation.size()).isEqualTo(16); assertThat(formation.get(Position.of(0, 1)).getPieceType()).isEqualTo(PieceType.ELEPHANT); @@ -38,7 +38,7 @@ class 한나라 { class 초나라 { @Test public void 바깥상차림일_때_마와_상의_좌표가_올바르다() { - Map formation = initialFormationStrategy.setUpPieces(TeamColor.CHO); + Map formation = initialFormationStrategy.createInitialPieces(TeamColor.CHO); assertThat(formation.size()).isEqualTo(16); assertThat(formation.get(Position.of(9, 1)).getPieceType()).isEqualTo(PieceType.ELEPHANT); diff --git a/src/test/java/strategy/formation/RightFormationStrategyTest.java b/src/test/java/strategy/formation/RightFormationStrategyTest.java index 36d19e1f16..898cd67e82 100644 --- a/src/test/java/strategy/formation/RightFormationStrategyTest.java +++ b/src/test/java/strategy/formation/RightFormationStrategyTest.java @@ -24,7 +24,7 @@ public void setUp() { class 한나라 { @Test public void 우상차림일_때_마와_상의_좌표가_올바르다() { - Map formation = initialFormationStrategy.setUpPieces(TeamColor.HAN); + Map formation = initialFormationStrategy.createInitialPieces(TeamColor.HAN); assertThat(formation.size()).isEqualTo(16); assertThat(formation.get(Position.of(0, 1)).getPieceType()).isEqualTo(PieceType.ELEPHANT); @@ -39,7 +39,7 @@ class 한나라 { class 초나라 { @Test public void 우상차림일_때_마와_상의_좌표가_올바르다() { - Map formation = initialFormationStrategy.setUpPieces(TeamColor.CHO); + Map formation = initialFormationStrategy.createInitialPieces(TeamColor.CHO); assertThat(formation.size()).isEqualTo(16); assertThat(formation.get(Position.of(9, 1)).getPieceType()).isEqualTo(PieceType.ELEPHANT); diff --git a/src/test/java/strategy/move/MoveStategyTest.java b/src/test/java/strategy/move/MoveStategyTest.java deleted file mode 100644 index e271012d0a..0000000000 --- a/src/test/java/strategy/move/MoveStategyTest.java +++ /dev/null @@ -1,10 +0,0 @@ -package strategy.move; - -import org.junit.jupiter.api.Test; - -public class MoveStategyTest { - - -} - - From e4112254c341a264954cf4f5d01a27dea7b2fd4f Mon Sep 17 00:00:00 2001 From: SeonWu Kim Date: Sun, 29 Mar 2026 22:44:02 +0900 Subject: [PATCH 81/82] =?UTF-8?q?docs:=20=EB=8B=A4=EC=9D=B4=EC=96=B4?= =?UTF-8?q?=EA=B7=B8=EB=9E=A8=20=EC=82=AC=EC=A7=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + docs/images/class-diagram.png | Bin 104455 -> 335193 bytes 2 files changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3fd3e9ed7c..e08e0dce99 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ out/ ### VS Code ### .vscode/ docs/record_memory.md +docs/pr_content.md diff --git a/docs/images/class-diagram.png b/docs/images/class-diagram.png index 9ef20f4e7561ab304ef37580455ce86fdabf95a5..1ee5e2b95b9b958f64039db7aefa6449a42134c9 100644 GIT binary patch literal 335193 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

l<)MB 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%0A``6`EYLi`aDxa+XeJ2Q4 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

lq%}YJ5{PX zADimp*iYLKL&ZaW)}1sR?Cl-+#cT13+B~GM38PsmD#|MU^IQbYDn4pn{4OA0*oUZP z8r*Dqh6X;N`tq7l2LrJe>3;Yw7&_HIqt&Tucebc<{EoYeed`|KGdb*v12^W-%g|F0 z(oGXQd-gta^YsUUJy14&G>iSQjc`Q`hQnI7On)_bkT99dFU#7II1bvtPZ}Bmfub`u z`}E~857Xgl_jJ>BKc}J_v0`mCuTF2a)q0)zY!wVLZ5_UzFG;D6jyP?4?M*uTdgb~+ zjv=)AcibiNhP!73)_OqsKKMQYsqSEcTd=!4FaiXgriWXz#jmHuQk+0zU<)3^L7;Gb zg(PM0f?@F01yPuUS*DK|MoB{&H(-B0qR-85i`2ZzcV%q-)!C zIpu^n3|iAB++3{r-`jnSasyyXu|l6(piz#7z#Fd+c&*MGt@_(!)5gE4FRh6j(8&rY zVgYm(B&vGc4s?6SJ=b&~OU*z!@}8uz-h%UX%!G)k<-5uYjb8v7>a^6tl;>GJHuE5$ z>P&s|b^!@ZgJ2Wn^o4v2ByfQMJJY_1Ed2=M)B9{X)7CcRX&_O#4Jmys|5OdwG{Zrp z+$P|gY<6jcXDx!mRdq%x?F-^MucF(aXM)zt)8 zA5273!j}H`k+>|t^zgcCfl^r5?fA3iLH+IC1|yzW&7ELJO`hCho8^A@5L4!=9sK8i*o%NrP2j*8y1%!FOVKyuJT)VC*@MgC(9m+l&R`{Z!!A1T zhZN~r;l8vclxy+B$#QD(0UAZGehP4wfI(4LCwR7Yc36QEK_OBwZ-NV9ALAV}tfO^G zxmT=^3O)LUxs+j*Qz&>l?v>)I50>-3l-i0`aPgsKW8Atwmo*)bW0MDO?Cb+aM|^uD zfOBJQFkf0_`E=Ar814j-gg zqYV~6a(8PK#cHDdJ?RaA$#a0k3RVov-#!`glH(g`c2sG#)+QxnHl(#j&<;=t7X2t+ ztgfxC)wuA6j?W1_FQ#UK3j7AV{;A|Xd%3m#*<}OnqMmPQp0(*FH1`@&?)&U!$H$XZ zfR@@SO+V90p&GQGg0rDhWTXmCNG%DS;%~<+N;iQ%&v>z8Ct#b_Ym5m1dkvgl=%)Li z_M4e_GmXPN9l%OQ43oHxgyuN}FYJOsd_L2e_-xVgAGYiiKD37*20>gUpEx_# z>6k?WPGd(DWLr#`B>sc9;T90C(ek>yc@st)hOs-EI`!%Ls$pazo-6K$d3y#S60 zc=Z^lRs5Vh$70N@hlr`)BK;$^YJW|DaIJ72t=Ir^y?p+h%B^>#Ja6t-uvpgv3cUJz z1#EjSTObuejw>Jx0Vw&>l}xA;2-zuCPht(YdlyWnTbO@2f6n!2D#J!-!*sZ?Wdmo{ zVUP0`s@3qOj$F)1Daj*QL$ot{HJ(T3;Rz>HRY$1Tfg?x8jX9_~)d_0JtLaQzo?hH3 zBWDU~951YLKxtL~J8(2acQ5GVVo;ZR&0B9nfoEsfw2LE@N}8R5*b-RLNAWOzVqKd3 zi`cU{`~}DBj_+)E1GztZV%<6ji2jZRkq43jItZotSDP#VdFXv*CKgFOdy{o*zm?eN zy942}roB3u3jmOd??MU@9P_NtAjTa!X&D9(wNg0IDQla;vk7cGocRr zGJ}+suz;TnP<))z9(GUo1FEf#)PuL{Cv;-m8McDsAEGq zKBC5tMxb#-5Y8iYC6hwcPx*hm&SZOwRsK)Gr1gukmhH}f<%@F|&gNTeCJ9+#!a3E} zvA(Z`h=c?n3G}<)ZsT7;LS@n1EV4KKF?<=_jwAc3QNs1bOYDq-0+H~y0{91C)KaCW zZ7}Bf&~FHP`wD?~#~pL74EhG_@r3(BUlyM*OrO!Lf()_!ZEg$AIb0V~-bM<_&>2 zn@K9gu32L5!Z;9m7SlA=9)%uoSX8%vd6LVAZs1BmV(SYNb`|+LWh1v{cETw{buFeN zHQ=V}w&~JT^Z?~nkfYaZYcT6{{W#!A#Hf%Aju#ln4a=>)k5LgB5p)$u0*Mf%Mo;L- zn)~x_HwA-D&sPU6@RbR;-o9bz<7@Fk=Xw0EK1h5I0F0<0ybYQ6LkX&hJd4R|NN}ECP#1UkIP^htaSqOQ?J5ie&N)yrB7yIMuQaK6u z>U!`tzW6~6HS+i6S)e%R;snB@(M$>{#UifOrJ;t~N42gRau_T=>>ZFMBDrr(%LN;8 ze9J?0K?!HZQz~6SOPA|OO9DL=d;$S)H^)8kf9m7EYfR}jO5pFk03;lZ?oY?hCY&E8 zK;LvYcK{ljT6}B+FK26Mx>O8OOl$i_K0Xn(?4>Ev5}_4|aW*>JvdS&CR4%fLUL@4` zIRWSt7*U~VJg&te!=TM!c`KqM=gMglV#{teY8djucQCvJ??9vyE6yP8zGkatOZ zH@Ai*V~1|FGL7GEv1Qbj$$d%w)e{$7#rOyn(ffQ`5FIy>ZwGZK{D|>UAb6lhh2p(J zup~(n;dz2=X$s16*tDPJaCf8=BT5@4*&9Sv_4PY1O>*sxhtOz`aAE)px+SL>%JF?a ziDJi%b~@M}d(RoKM)g$qtWL#OugF^2r5y6P>UX7wG#OB1Pk6vL6zMmJhX2prAOJx} zmGVk>VsdolHx}?u2M)vt*eGjux8NbPgDCr&Wx;bA_6!*N#P$L;kqJBpT^{?$b7l>% zzgMXYyw5J4TdW6Cf~cyPvHq3tZJo}|2f=z7dWQu18K$B+)uh%BY)%tuFIbP(_h14D zZh<+(3pGaIKCp+V-Dv&Hv*}?wsFADXzDZdR^->sQ-YEgY`JE+(lSD#(iJmkZ(>y^U zAzlTWQHGpoiec=W$BEf=gU#pnd*G{i^J^H3i@+$kxC_KJVi>cz>>#){rzIRE*h4f% z$HtwuA0v6r@5ZPsu~Wl=&3HPO1r93i)xtVpo2*NG^o`wy{A8mS_s&KNz{co2z7^Um zKSiQE?WelO+g3vZ+3CkK%MmChO@59m;IsI)6=Y`(~kyN@yoI~${_$k-HBtR*J?}r~>S4&c2@Zu5m z{48c|JS302ioZL+*Dy|pl~Pit^{72Ne%BF~qh6A|fr_)QrXy#Syk)D8j@xP+Yz2z> zj?RbH&(GFJ_Rm+u_ioFrk%iE@>}2w8ri`IE^my+vGEy7UM`gZXQp-S3Yr0o)aMALC zcLBy6@=BMR$DjAS*hzpF{F;9iD3Tg^I}DqhnbwSMwQ!AYPm8%i_HU-(*p?=|lZ^-s zW3EQtt8_R>rkp4+=tA(*HDT@yMMB(B&_4}%R~Se)#rKCkm(FIQ<_2xxD#^rwxAV#L z?ZFf1?x1+*$Ee<+f{M%w_~V&B(~}~r%ABqsI6t4j(Uhavk<2r6sgzlw9@W7^2(87@ z6nY2rD(w-{whAkbfSuNCXRs01NCV1!q9q@s(Zg3>D7;mCxjM+En$Ur0%$iOdQ+*{A zN}h18O(DmP?mV32PudDw>4VN5NISN!SFH1)k+i~!je@nXwPW_5n++Gzi;~u3p!#8w zBncB$&m5ylgVe4b!374V=8~=`B{{yGybfEoI(BC*e-;+o9m8PKC5aZL&JW#bcd$kj zWXGPUsK3um3OG6`&6P_SOvWXF=s|WTAIB_kv>JK9Bl^6n7d$LYdc2Eg@`SmI{gl!D zuGPaXtKZAE;_9W0D@?H5$dpmd5daFdh0n!l0MBX2R+O$}MXATAs2JpNm9RYy<9bjP z^wx!XB66{i$TU}z>3sk#^#j%;{@)6s|Lde)qD;iQoD2$>q5}`O|8nYkRU+T<1`KQ- z6Lzirv@3uJ2#`Ox-sASslpFsjo#NlYmEkAqoT)u{>fsVkg>ZLt7__f*LA&0bNJZDMGx*|@eLRLNFP{X zWk~Y!hrK-m-<%e@_THC9gq^&;MPekf>KdwuzaU~?gepO*W8vKE8`71bXWbBWUm%r? zbb{aw=3~gfjOXPe2;AEcLxqJAAgA}IzO4<_%g)h9tfp(RYwy}uiyu8Fdl{sc5Un29 z&s)H{7}oibtzmAbU8a1YqhkkiSbtT&Ye@>pr8sJ9U-;c?2M_=nBkUgIv5wijXL0Sp z;lfK#LFX^|&TaHxjyS*f-T*RG{`14GRUlUQg>koCU5+&s{|r+1Z&5XYD5-|%#HIpJBvlC7uVvo@uD$>WTC0C(SYzD zM{3&t^Jgf~6fL|eS&L@9x6>ocKdi{d+V`DlZ?P#qxWd47_jgnPv1p=DB@!@hAQ;}? z<+stl|K_NLCo*j&X@5trn8Bf8-DB_RdJ5OSe}lirw~*EnW%nec4`1}tF;W*Z%8NBp z`N&|l^?k8H7uhtl>80_)gp%d& zk000a9sJbhw%mDk&Ls_(rc{=uAw&`ha!D!d{$tHIlA+jf{1*v^!^m zgrmXQ^@aqLhu7{x>JkUhZy2#C5aGWRzN?&-Q@3|D>|^Dp#A^2HTQbSa{HCf|Y|dTp zR*hd?pV>9Se}|Fv4P#bLS;7;-k}QITdQDaIkfZ*js%Cr0Zf~|-?~Ijov~0U7ca6_r z9gJ>{t-4|zyM~rm7)9}5DBB!qu~uhJ9c6{vVYvled?ROD%;&uT0=UDyiuT^Nv3ZJ* z8d7ji{bh#ogZu>FRIAm857||Ph4=i}Q5|4?(&!=r|MA5onV9|)3r5K6V7+$q&UEY7 zYW_DlQBhG@T67$A(!J1JIjK0wa2ldwI;+mvCGMy(TvLT0d1i@9mu98AsHc8cT+!5u zO<4421nc(zx@Vjs7MPE0%^;&l@eL`Lb#oiw$UBq8_GhabgS_{+E(2G9F!YB#-U_;t zRrK+r>esKv8~YDR)A3I06dx_XT2QXc(g< zKFAFPc?xRmvBb!5X-4{5|1)2Wf$sPo069RBj<0p3Ch zdSfu${Qdj)?3ObU{3Kn#%Gz{mrlsQzQj?Cn6do8jTlISYajEPqH0m=s+F4`=K1DH) ztUe`;eC#+n0<#XofHh5BxXczt{X;<)adR&b#OnufH?_iKc$j3VSn=VJ$SxS2ZjOk*^VR||nk3Sxxja2ZNcn%Q1E?juU=$D&Do zCbbCrjF&Y0M8f>4Uo)~w8XLtlf5e?RdN>e(+vRRXi4ea0aq#D9;1v}17b)!@SSSZ} z%dF;)Rs(@*RVN8)fy@gS6&45@BZF4J(4xj{z3G-hg#ttl?;ANf}Ti}4Lh;b!NyeMZD~${V%d6tZYU_Lie<66TUY!|jnN%Qns|3dBqS9 z90nSnr{XPG3qX~!Ut5F}&#+-)&1xPG58P`{CBUV^CI0kOm~#_p-gPTJXquk07;io{ z$Dhw8ib;JbJ@REm8vC^UU>%?7bQ6;BRFnN;u!-LqY%PATteb@gL0Wlom$;8aAGxsi z0o@Pz_z7lxsAVV7DVEIJY^x#m+?!6a zWOY;gjuXx*!_7Yr@$aYEJsyFGp|GGpukWDFwu@`iAhC)I=r|~19yl2lMkE;PWv`dX z+A%qAiV{?dsP4?O!%=R^EK}gZjq+K;7MEDDAgpavUQqS%1-g+d9K;L#qgE zG~d8}k~hqyztD2<+~Mu{0X5!#zjwH#TkRb(EiJ4}KnpqEl%M|?%v(GMuS3at?{(6d z8gR-LRh4bod5B2fBdc8qa9(^Tph*d%nS-<$y_WM3;EtSh06p+Y)%88#xb^gW|1B98 z_HCwio82#8v$s$Lb?-gPt!?7GKZIEhIT}oS(Q5~>=1NRYQ9mBvuQnLHqC-Qf?}^1x z4SLCW17Gst?Fc1VBYmWQM`HjdK+p5(l|Bt34U_J8q9={MZX$K5c<%Mo*3hGf^ic6G z14F?9U#OAQTsup3rXeQ5o$gc!ifH>mL!FH02=GJ|wv|O@_&9=TzSAifHxp@U4HB{H z2W-xIQ0yIe)Z(solby~tB2LBNz!A-@=)D|Kv6e3*;r*Ya9N6?840;wWXNU7f!`L>e zuM&hPOzBg|j`9C_Sm*>$EhT@S9G2*%k#k4!M7E`odbiY3t$z(v%V4=8XzE?=f8FoqbFnQOewHA*r`c6FD`X+zLF zYT3a$&vnKy>*tRjs_N<_P4(20+HdSTUqi47>cqXJf)L<(8}#of)YV&Vu?a+@=n`JtLnz!>Cil58$RO?xg#o znKE#`At)VFk{-J{4@b^K3B%w`_(bSlUIFMte_UJ=c@gv<7u(qaFY1eDyBfx?E^g2f z2THc)*Dqfz_X*j}$5#?Kr`@A1Ry%l6&Ca}y&B@BA7Fn~$d~ir?@6=j#K580iVB!ME zaqDX?U5nE@a%E?88dp};K~&5h(s6)8HXpA02McIeUM9(^PU^wje#ovLr4z80tnh^5 z;&AO=Mc0-8Q&%K1pc5_!2B*KIyw~u(=*9>*1gep zDDtY;B?R`~+pIe7fR6*U2kR~K=nnRAoq2qrBjCCS*)rkGmIXXzuUEDi6`;EE&Q@DO z0A}AwitYW15#HyN$2IRXiO=35oGU*3F>yI|o8yu2an|DAvXhO*pO5gjMoOH(n-pUo znB$pgIK@GA;=1O33>{?^fRo(Y)Qj9aZ}Bg_(T3(LL~uxXaUCvBPOw~0W3NDI?$e_T z2%}tO4dMe$uL}hx4e2B?eI^gS^@lniQyOA~US`A-+4@XA^po6r2vlYRhR%h&Amfw* znJ7?Ro0IjfXwh>{WY1pVJ@+l;O4T$MUR> z?r?KVc&TIu8!sP=vH1&H;fHcO!pIZtKfdG<=!7cIZTWXZU>#d zT9$RxKlLwuwY$Cd?aSl6=>!uV*|XKDC$^xt9Lk^ly0S?d-`3K4K4{1Q?8ByaJaAUh z6tSeK2_iw|7}|UmDDJxPNkto9!n&VPb}zP2a^#D2?zK9eQQeVh=ZcOGEGdk;8Vu8O zWTBr#Vt;A+67rtz^u-+3M)ih}3kPU@)W5pAQtP!?vR*b%mebPF`0m{`N=~2jy$`RO zZi^r*KE7W?MJE!}`}_yQ4<;qyxm`Hlks5;AML(-me8(Zhzq}0#GtU2gjmD$}`Y+4! z^5`oZ{$Sf#&q*lLZtqJ9rG zrz6MfH4~p?qI;8;U9-#VU*1&fd^Ev#R@nb(3t9U8`Fa=W#zlkb9Cl^k;R|t=&?}1S z>T%d}Sfsxk{GD1uBT;QiWmE1+NOL7IT6>r(TH_UabkBj(b)@nWcDa;jA|00QgGd=& z4-+Y=ut?b`Rr}`|??n|gB7=%!q>YSP-=w8HjAP2{?G5`Z>-S!CWOjD(>9XGHd$IB~ zU{kqEMS#_(+|Yeb#*Z&9{&j$ajDFb^4H3r>C!Spq^;@~pDX~dxB&TZLy!z36ds!yz zp|Az^tSOcYjIA|H`M`(iEOZXrSkOEDbgON6xQR^DyYtcdJTkn>>G|t$=9#`dQ0T4H zP^q=eOA1C}Pm4_%rN_;g%ddfO-Z%ImF7nW7rF2=gBLb&aS(1~pIXvktV(D9Q58jtb0ux~~Uu z80Dl%FxFY(17>XAd;_bHk?F?3?K-X%%$OfKF+5A;3%$69e-2T@1h@}()(6fIf8`wt=(OWh#@x=BT7=v`(HQ=-EjPt zij|>`gWp~3pAQ={hgv9%U^PJdzD`1@99k*gYL}LISrqu&mfAOhT{CueJ%ykKuMwxz zq5v8G^3sFEVx`H8r*&&}X1$NeKFQ25oWuecE#V3YbO68_eby;1kZX>5(Ak(rEu8CVB#%3t`YdaMx22m(^|J7bNeSP^o);#ke5e+mY7 z4eF4VhpzJO6WTM;k2FK_7Bu67es^NsIgo`pm71ec$DD%8BTFO^fwkaRgW$jQ=(1Tu zAlIlMTZVG4R39~aZgM;3%ykm3Zf_jYi1*qG!&Jg4CxU1ND7-gAnMQt)Q~Mei>J^hY zG<;k-csTfOiC{yRbT~zQn4?OT&;1t9LY`avt>GoB=je^2z`54;c(sH?TH~f7=Ck^? zM+Tjb_(eHcDexxyB7@OsfFs2ChoN*v-uHfP$Te{J^??`2+%*nxij4Z0O}6LeO-FJ{ z>>qL$o0mjsI`kBqjx6}^v4pj~jv!d_nX6CWzpr5?at3tjAs8tea9An&A{m;~P zDEydyrZAq~M#1BZMmKX^k$X&m!G&Rc-FlxTgf~ZYVz0-wSaPQdisg6l*0n7ZiMGdl zDDwxR+AfiIBD?Q0Gw%xWdVDZ4km$S4+g{p7^2==J86SrQywdP+ z8nuWNarI#x+r;LGNAnU?SH%!LV`nh*aQ?o>b|pPAdmsFK7E2aY%!@}f)Y_@OArxTx zkXJdfNqcF$HBXrS*~4i)YQOmrtS+V}6eBHJ!)RBLf`G>)91bcP4vV74hg}2W$0W%+ zLlXTXA6Vdp<>d}vbIfzSy)oe34d!f`N#>O;(#T~&CxL3yWB>p7dJk}_`!|04p;L}Z zRwc<^DUrRMBT6!kRAiH#Sysk5RwYShHb-_zHrcC?aco)Hdt|R;{oWtc)ARlP{{QQ8 zxz6R{IG^{p$LoIGuX}Ci{l>hX#6ovQ{;ynw} zT$=f=?09C8OtJe`#G`(i z?4x^utfkf_N%7-3wYkx1>s;TfWrpS2>w^||@V*p0Ej)1saSgTqOp>D)u%B{@d*^Qv z@*ZIWdLR?r!`$F4Dp1zYcr@QU8)y7 zz6EC9$TC+Kco8Jf4JX$4o7xiMV$U#!1VLM#tHcnTWyqxe-LMTZvTv=Fo*a8kbAQ}u zdTK(oHYu0isHE-gMJt`aP=TM9XJ0p2#HcJ#?G2molK-^w*-5?z&J8$lWV^epls;A> z)^_XS%)53exQ3C=uxH=Z-l~CTe{Ne8dG;_j^1$4v5ScXjF2@pG9xBI1(ZgRvKe8ae zp9F4RP~h8}8HT)R!FAJYZlGBJZ)`>Pwz}kO`2Q*@#OZ@4u`=I1_Pn zRaVIfsdR*U>g(%!SGz<^n42#d5RsNycOF3oY3AT$-14mn>iv{<<1pdQCzeThIGTJ` zDB_O13MSxLOWac$@h??ZqLN?JwfW@6$M-*5;@9}*&Wm6bn6B^$R7}o(JLgbCSG4JY z*nFT9DhL!2z(~j5;8)0URvQXY+#s!++YasWM%^H*8+IpVd82+XJ+bO5@-(<+^GCW} zCl8gFgcoe~M2J%)1UR4rPs^6+xS&HL;hal)!G=rh)k1U*@a_;Rmro3EPI5keyaE&o zZE|*8X}Xz7S!aYD8$m8S|K*G`6t{H|3y19%f8Q&!X_W{Z{U)*;StTBCne%49n9WbH zF=ERZCxXp4KCn3LX_>_Q=(ZR0ECX`?bqNK;i>p;*->LF?=3WIFeEN)=vsoig!<4fL zNu!bj-D4G^>>pe{xSTfP9y^z;#FJFyt}2FgSG?w>;r&tt4CICHai326wwYiiWR=3FhR*F1aLuXmldW&4E$v~+@{;3FuVB-q>A6dPLzEN}Q6 zE3`A{B->2X#<%pkjMDDX*^MVddITMA;avRAvdVd|xaEY;{;go1I*|%L9ii$Cvot>Hn(h2HzO=Hn~lhM?-%wJc4oBu;trfDO1-D3|Nh7a7dDTI%l?;>dX1JeTlovsX9($q!=*e zcsZoZmg}+HJ_r|;P7q9L6+{bd(uCRlioUEf@*unxxq;@w4;=ir*U|sTTR@Hy-plyV zyT?8p?QP{xj~J+VOKVQ0Z5JqkpGq*K=39v4GwlEi#hTP=Q%76idvq$6ZP8h}#dZL}a$Lg}e)qp&&WS9*^b& z-uei_9{LIwp4{2u543^e`U6DxS6re>hi%PO>X?M!yQMNXrK-!Qn@))#_ID!ZSeW*s zZ3on#KORa1=U}^_ZZK)zMagctggl1SRU#=ya`3h0Dmq~_`HO#4@`~Jz!EN?6@r)X< z97Rfc>vKJOk>3jE7LtGsU=ASi)%UsP=?L$l2DaiwkK>6mmrNn#Qr_&Fq(@Jc>=Iuktow+%?N^bBem*4XAiIh7kHI1jI+bE=iTH~HD zeY~{muhyD>7z+@Sf%BUaQJM4k71-(=Keb%T&?TWPxdam1yOItuwt+f7zC!T~^pJ7a zq2(E5aqFY_F>V{x?Gy9XBh;T@GJEpE;R50>c$~YcdV%!gamL%;dbCBAPc;#sLB^sb zPHNAwqb*6^67{Q?1r`{8k(saB{*sANB$cNu&jS)E)ByUBUrl&bM|#7bawX5 z?fn~Zo3aHyHLw{+iqR6@V!F!BEu_<*d*Mk?VJ|x z-@XC1$pBO%mI%Zezw&{GeB)g`Hu})v8yV^z4o6$^0vWIQsScQf-?7~*BsYcfy;3>% z@JonOs4M#PTXightKnIr>G6-^NXPVzW3#g=^ z3Z|jHjWtv$ zd7Ww4*M@mebc;37+37sBo`aPzpuuWd(+G-NqW105{VqI7?))L}5RC?~9se_l82_R> zx@%y?!7Bazl$K=S5-#~}EtMi+^2BZWX6YY4ew^wxmH8|v|D-8eq&>XQyAfiZ0^}E) zCS-!UqzOdYp6uQ%lsVXWu;DC4KcYXKqaj$6J^aZ6#WS;UlhaOHwYH~w*1ui~eg%4o zaP-G^c6acI&v}F5Te_ATD1?a#=~iBn1NvM22B!1n+;-7}k~M*boe8$S{T*x%4a!Zj zZQDQ^>pb%F$pDF;ALgH!IJOflfn_cyLMI__gLGf13*opYI#w@2FWMaRfkNzQZq4Jz zv)NJ-iaD!#Dbly_UxNBURR5=F1qHlTgv__zWCBMxL8mjM!Cv=CJ;ws1RyxZZoM4p2 zj|54Ig1g$f=wz$+*V}9;+a*LPVVxdUrYaEGK~o8{u&jptx|Y@}=cXPDPkt zTEN(mN8Y6LS>R97KfhIXzL-GsbH4L_;a_**;8L8GAh16K^M+W!Cux==%rHK>dvWZ< zrer1T)Aj2<Itd2)@ zP|sm%@pmA@CQ3Sese?`Q927kqej#aqYQSdz$x5)>@~W4GfZ}w$smmw_6qW0FK0T+D_e`I zR6vklgAFfxeDadd(RnI>r_%ms%b@M^xI}P#bxhebp&OoxIJlKqVnhBDV8SM5O&f-1 z@$e!_+kGkof{lmQj?MT{Bjo*YCg|nSkai|zGGO!0?-qdg9kw=fmOwmFN@=&^vaL@D z=gVAg?N>B(%TIS$yjAoCLAPSstap!ud`?LrxCZ z-FvMLRTOeo5nqh$6}bQR>8BE40PisYLewU>ZN(@-^_w@pJ#hko8gG3ID9b30^=I*0 zG3!DarEBYQF=DEI2W_}~eW1+qErbSt?hFpD2E%b1ijW^c9#JBAKd6VHb}Q6X zH6q{EQ-)rVQ&(5_d6y)AO0CY2bZuqXGA$kgbENac=H$u*%cTJ&hOTqmU}7WzykfH4Iwx%cP&j|Yg#tLhF3W_1aum4 zwi6Nb{GnZUl7dtDflwOI@36X^ey{}a37=V|Sn;0Eg%cO6t<2X#xDTGB zMTF1?_d#A01Q0^-RFb390iX&t%xaFq3W7G*$!#r>gwFY8=Oqb4QaAI@>Cc8v<*$CG z#zcvGx|Z!BYlwEqc5Hdks(s(284{4OBU{%yDakLB5#l0PDTw7$y zf@6_{PIoxP#85s-^75ST?nD|-as-fO(0_T)^{;6F=Ll&{uGbXtJ=gcGdFaf?||40c-zdW4< zGKX>FF=_8%6c=9rqH1!Vuq62~e1v?Atz>#?Y9_dwTfCtIOv0v3kpg9nB0o64 z)LxyQmw~5#hVETBp|c&?pZf=1@H1zQN3g2u>Ke2g4?Y6NbJS#3zbiJ5fA?eGT&Q*D zX7(xWV%(XsjhCgF!}~8DB^{STD)}G>S!}8ipLoV<_Vc;|_V>zvM9Q2NbvbP_x3eWN zJD2>ex%(QaMRvhs?>@x-roi^ENTE4htW!hiCv^4s{cYGNc^}~;z z{KUa>|7Kve%uP)f2}~kDIK;Hxlw&=(flqpe2G%qZ7xWd2%VM4;yxZ3Dr75#axMOv$Ms{)LFL=e zNxS62NV3z)zI6PyT3bl0;m3}Fft=3fp_L|XteKdO^T)wum0IwA&Y=|v2&a0MM=de6 z6{J6QHEKilJ{Rp?7*cpPcH6JBt4mhJgoMPeu!63hr4%)^4Q6!7eMQzHiTnw6OQ&4# z>H!Ubi+G(Eo-(i^EHWHD2^x-@ucd$ElxXZ<0qr50@MW`%ad5dc9z1v#ctYFwpGVYO zgfDNzsvI0?4@%}Z_gKo&lwM#FoM5?E4=%H^I1JtfGPI;T_yDm)U)h=*eO=CG+N3vU z5@a|)&F)!IMxS4O99#zWc$TlVc+VHPK`CrEg%-2hd_^mwVlI%k*45oTMZ?jx60x8~ zQ0C)EfVq5F1};J(2h+6Oldmwf5D+$&Ra=N}Z!8p$fg(O`sM5=F7r!QGQ1j-@LmmU; z*wzHuzWAHIPw}t~NdLSL`CiN8;6{PmN+FJn(79-?w3&)x z*M7-f87OVgOoz~5B#OLc<1s4mnql#BdI6lwMtbo~rNsLt^&I0Ka71?-#TfnFV-!|L zujtlUD-!j+=S-Yp*4I4<%3mRCiNS{%{gikBR~>Ak8oUnmmstZDwb5T8!b53k7S6(P zEpC_h69*;?ORntb8wzfe?|Q<6TIfdyU!qb-0*M%R)(0T`8DWbX_#6B_vLZ+|;*K9e z8ffVR(g}SBI&1cX=^AlwLYH7MrWQ3~&dnNM!R?j7{6e?FdU@S>@164=Z^^)u%3hW` z4Amh6+6_Mb)(110&dW;k$$exa}|Kt*DH? zAM|zIADG$48vSAxiLtT)D6V@nOv?9R@z(8A2yLeCi#2Z#BRl9ux_|OTNoCBPPe#xQd_>mxB2z8X0h!)1dWAe?5@t+Q~#GI!v8~1 zc!&W04nF3|z(b0;-{*vGJ=(+F6@a@_)P(IBMNL*)s(wwo4G-o8uY=85Z;uI%7nk_B zouWJVH96}ix!9JoLd@P85$}N2ZKoT->;k33!HX~bW9HRle@6fOdVTfXuCk-^87{2sur^-i@WfC*tvO*5dd8B;qBVMr6v4aB1F zRWe8Wvz|^yKX~wwL!hlj&C7(y$89rW{9t^ZtrqQHvRL}hy7)N*%* z>N*>I_dhEDf%wX7e!>3qKHgvOS-1N9hYwmui}d=PJO1zpv=9+nIIX*2 zRAX(>AzUeLXgPPh&MoSF+uqWc5D%+y|}0Ycpj@2slGx zT;XiLj!6mp&~+=F@5!mTTZ7mrbYX(D8 z$nweSJxP+7l;dDys^k>l*pXvWXAbHX2R3noQZF=&+ik^OdT)Dhcj5~>OW_ARI9}_u zZcAU#Ba!6-R{61_Pd$H3CSOG<;VdJkP4Ev2sJEw>8Ow8YCi^02e|CSXS!LValoQ+B z0jG4VujE%+^Rq#-Fw6Sxw}^S_nPC4R`d#Y`-P|Sx;SQ-xMTun-*|I>{r~=otnr(OO z`T+fu7y|`%xB6GMJpxv@C`;@XONBJXsTT&rS0t^L@~!t$yabmLuxmm^TbDM)7xkUL zzI3f$B8s5hnxOF;So9HR=}w4t-HD~^^zRTApQR|GAfJkYjpf153VL97R!G)+M+*dk zNd~v+*IRuIN;Ca3b-N`39gnUv2vI!kzDSM`ka{|LuCJ$~@W|M2x)KOOjw2?VhXe6x zTG0;4t?#H_MWLT#Cha`tIxnbgAPy8Xr`PWSPZiafOTsO6ec49xX&%Tapc&PkZ}oF# zHhQiAM26IR41i98!o^g3lhRa*kB#yjhgbsUp9^c?c8_!qNF9JGdiOT2j_O~>aM_OV zoR?Cb?&p0q&EgRUdUswB{6-eKn(ouNJnd`$_!QSJW#97L z#!l0Z0_K=j`l1e^S7RZfnNoV+S+P2%Vs5+ltW8|(_`;CqmZjGWuUPJHMDdl9%6=To z0YTEtWB)PZ3K8>u+4)W?O!RC6Yk5JP#>&E+ZCdXfn4AQh1%@r!yIkN$fZdj!fy1SG z&k&N-)tqysv}@aMvdZVZtZqEI6 zg#1F}F!tg2%EP4!s=2(dAKmPqw=~m4p0>V9 zS1);htsMOFS^c8+B!k3{AWmPT7z{GIEh)r1TiE@=4Y#$KPD#IV9!*6fqa;7j!V+r< zh`zkb#35#?ExFQhr*k$H!mq#Qm>gr>%*O0GNAVcE#OizhLr3^-@f8D|rxR!&?y#tN z4~WGVJP*y)NgrUYPENN6a36ROQsUGGrj{S@jvqg|i>*sXUd&6qV;1dvLCY;Me#`>C zqhAwtPc|PN*wDxe85C^mOLc<@!KUS4dgW}80K7y{a^bzA5eswZ!k&;>lC`}2?M@T4 zPE+79$tlyx{Jg?4%>1Bl zQ6MjKb7nhkX*-R+tdod6ixPhce@91tS?QD8Rk}^j$vgkt4RLo-$HW9wZ4ZmXZQLFYU+E;{%*Zi4AuU8n!{Qx`%9*S@Ros4 zn<4JXA20ht%6;gP@sz%LI@wfPtO=~@4V^?$MDJWrPLs&w@u(0-JGpeAhtzYEN_%V; zFj}+hrrV6y`+9u}=A%L3?_>WPX$bQV3O9n6!|$J5Uwi^Ug?zve*4pN*K3D$^3SW_o zP`JT}zPOx}089K0`Lp{Wn*zNYfEg<4m-OHk+HaRKaEM8vFK^GcMrSK(3doXf^;m`T zoFGQ&pZR!c_}DWz*W-31`zf(m-Rp?CT-%*DH(@i+OG4Xr7fQNR@|zQ^8$Y)z>&|XO zTr+WQr%;nj@DuWMgFm}5K5X5zR(Z!_vLUWM5R)9AMJYM#m3U(jHO^r|!`&;H>qZ*Y zWLPVY>Jf9%%?CG+MgpUe6BlRv`UttdEKCTSaJ6WAi0~!l!=JtwkiWkGc7B_>4NtGYa(bZRDY&a*T8LU3xyvqalKi(cAg;bzf3r$mSZr8M-AL} zR|G?(tB~rahx#DxgNKUDe#)5x@;QxaX7+A?!(B$V=G7P@R`6hV$Fs#DRo>=|ll^Ky1V2j(}aTB>lhz1}r9pHg&=LGT)SyJy}qOvY$ zI5m&0b0?$Y?tz2aLt{2yS`)qT1YwJVLYLb81rp1T^u6V^7iY{%(S(VfoTcV3Gk&N> zK{kdDVc!2uCk$Qw9@M-%2$>li@ys5B8TePaPiKXS2eYW$f@4UyY`!d()1DAE#Hmx#{V?{*>I-$-^@Txe{m`g@W(7&88q)CaMM(ez_CQq}HC=Sx zd#Ys@Nr|%Kz2%^CVsZ0c=3Ta69^=u<4FD=Q?SsSadhszO{41{(K+j0j5Ax+WJtz&* zlRPQ%hcyULy65ge_4jb=@jlLf^JEH7yT172@stR`W}+yIpPSa0@-%DhHUEED zL;Eg@&v614IbMW$rmuK^>mzBKSu^%}HEyoiO)RBXS=W3sxWUxO031(h`BzB|M18>i zU*Lq_c`UaJjQa(7qZr;1EgIW_T0aMMyak9GdVZ;4*D57pbIO9hs8tE6pkM9re# zKt-x)wHinCk|aCmew$TEetqA5cVd>##vI>EqH{+! zPJk&3dCzQcAVT#k@u6hDXzyty&KhR|njajP`1Zce+uKL=c&5thQE*f})dMWSnnsCL zf7UO+-pd4rk-_-&t6)c^(#tI1Aaf+5q{|L7uT>7hr>ZawW-?Dr_|BIt?3rFO6AVjA z5q?RCu7uf=gQ@vshTG#@X=zqZ^KNw$~xG}H4x z55Nb$XKZ2@=(3COCyFO41u$K7b6CFZ{TyoyYI4t2wHKy|g~LMWMlXPdfME~&{OCj!aHjn2z6;kInn1v1Sn$&!iic9EiquI7*fC$j+p0N)(F!1l8RO`Jf#d1P9nKI(g z(%{Jm2*n@n`RGx43YBe*^O5LBF$93gTw?;u&P(+#XOF&oqDr?)#VD|we2ZeJ&RL*0D-v(+P6?YVd=$+UBdmiKBL zrntA^PPse)<8#&PfTGdnv6j73$)TB+J&CiEiSNt0nkRxAT3#Ml6r>d8<~R9bKWb;p zWVONEj6W(D@~P{=Ze@%GJLem$0{6$8G5tE~ONe>h{R!I|6-~R>Nd=OkPd-_04(u;h z2?DO;)IS6tjt~Rj5h152Mb1!X1n4tO#yyPPMgXlm@2TZk4aD!V71)AKM?F*{R^~>Wak9cd_KsZd|iymlO=x!FPW%nYs5;DOL84 z$kr1nBA-b!fL9}78VoH7>L;hB@0RfXRagb!1pE_bvwKeN0P|eXuc2EeUe`C{GF~Ni zLMQ10o`p;tH+evYgp}U!KIUs|Psz`Rp}wp|kYn3l!S4MOx>+x|g>g!kSil<W}FPUwXGr-b-Q$RSaq*MHw^rrsq--s~LRuiHGPN17Yb+J&+Mk zXgRE3nv6_otZLW9tXha=A3Pi_1o*vu5)}HEFF+y~$czaeP0$%mYxk(Xh0o|uV4vw! z4h1kDMUI&z=NpW#xjk-pQp!GMJY%vyK$d@Zb2P(MsK8ED9Q$-#UFB3I7as0`9Aiw+ zdl7q7CEFy97WnmOP>#^7ZCrZC0adQO?Be@rqE1S4*%5o)nA}MG!~o@QEWm822itt& zJQ`oVmq0@2pcBVtvXs%ng;P@K?sTE z;G%8@Y?(5Vm_CifbJyj|28Suwp`(Dl+l)Y^%#qVZQZW1}f;Dj7{(h3f*KwP~sovn1 zc?dg+2J4S^fdx;1uzI5P`9?Fc)u-Q6sCsd_`yKEieL-4Jjk>|z8E1eO34-X*H513d zjLVymw(c|M&RD7xHeh$H!esrzxNK_LUelKB4tHWV5$?U6e8&<1G9^~Iv-{j2W+^Q- zNrP%QuuUL2T`Y;v7VM67nZdq^xcOZe-63PWF9$Pscw&w$62T1xB>GvBz%(MFm z;al!pR`4^39zx~rrbvF=wlN$9S)K)qT;ByanH;Z$UxLQO@fmOcT^&I#M^79#37-R# zqG%AitAUc8noAT@!|t&o$5UdD;6|h_!(s$tM;fYg6VM)efjPbUV&ww_XPNrD*B`}o zal*tU+t~6YDRC3O?NkyFFo#us%n*y5<=mQ^!>p-O^es11WFUs)5t%W4U3g17oK@t{ z$(T~^zPDkqyrD}>mx*XS_24h%fJ5^@gdq0Y7d9(s-sn8*vB#W`<(WiB|2&^m#G(AE z3POL}9IHPFf>e3#BR5ym@e$=v?({95>7eE6EV(06ivfD=5Z0XO|(G=<%nWRqd zwT_V5Ve)REw(LhI(F^LSKN<^xZvD!a63Ed++lolB-#_UPEvEVlN-ZExVJ4)#bmhvG zr}i;o$=5<1 zWV`EXVM(SG!)XGZ4x{szmL1FSpGbS5g(cvD^}FtRyxB6!tv?9l;*6mzac@D$q!+}| zi`!$m&fnB_99*n{g|sYR{lO6kbl1(TaJMj}U<>-&(l-OSXy!Ue=LcuocM715RQJ4s z5-C=CMSVMd_c5|V4vLc3m)bo~Nx+lVOdA_uy& z3@pJM?>RwpdinsU*_RjZJc!;H$KTOj|Gw}YvstsoM#zrT`|(-3Ot3a5f^WY*Tx61o zr}XtJkhH&^s=lxG`{*OclOj;kks zpW4LVShO;h9i>S!ku}vBN^f1d*KoUf=aUSEd4U8$toq0-<8>wd_5AM*_r%_7KRALF zF@#{kXdVi)9P9w53yc%$jig`S#sMipQ)uEWIdk@)7^uARFM}m-d(1#43fOoS=Pf7; z`n3D_j2o}-RG=&Y#g#3Y6A{8)-dB`M8T4 zcd<>pYQW?{nF;+a9)FSf!W1wK+YGcP9m<_8zJK(g-~IG+2SsFADWsEFm#k|a^>aBr zvcIhP%>bP4b&$h;f;VZkl31;z_?rJ4y~M67c@wpe*(JE$c;~s>s;}hNd1c3nihHN^ z#dMM_4?dqq73<=p+ur0rA?S48=HI)uC}m`1WaSX0ENI%o!0guf@d0C+`klp7Ih)tL zlyW?+2J{bW-OZ`eQAB4hWkPMCfP!!96tgr6sT6`b@I@(!?rLpga*Z5gKYJDiINAq3 zM#&H`8DSF3WBe%|>OYWzmr2zvd<268opsmV@ZoZ60Pnib*5~<6>M||sZ&D0+8Q%ov zpM$5=kD}=RVVWEiV-6#^Tt)Y|=*R?b$mff7=fYG|vq17OKV7?!3n7EtworsL1%cT$ za{>^gRLrsIy>pJ#wGtp4ZCoXDq6R(JED(Ec)^T;*1$nF=Yk9RGf&^5FUf7#VgZKkw zu8#MvldVbOKkN^$j96>Ns*i*bB+yj~Z^l|_;AZoZk+h-zY%dGx7C_~L^Sj+kZTHr9 zP~`@&6RnT~T;n_Wt?&C2pYBXr?)F2%ByyO7LD-wx`Jw97M!WXd0$9QSU_O+m+Z8^% zi}@S&kE4rod6M%EiC~rS$5lxy1_8J z?VL6Ikqc}OKbvv{s+m^`E;C0V}nBm@8dLX26P|E#dmRr(b z9pQh+e0M1sp1m~6go>r*r_VR&qgNVC@YD{Mi+6p^=${>X4mq*81QggHsq=1YuDY?< za>Jj%f@g5>R-)_X+-j-rG<#CmkINpq;5~@Jx5$52d z?Yq<+M*W2HlbyBp7Kf|-HD8MyLF&I^%RJR@%e)h?iNJ|Y+gmGhBAp01$R8T}6` zRm`%NpFTHu$%B-7fp3>|97fE;jJnKz-3$z-c>nMNWIoD1;{+|b^)`MwVqYL*l|Ph~ zRSvk7*8rghpezCUP|`M}BwL3s+!uW(xwkp0vrowsRC)yZhxvd4gMmJg;re9_3U^wfpFDFnih zZ=;ryBOVFOwVd}54rlt}eYOxB1HYu4#i(5ds8tlJjw1*BeN4LISesVe~De z+m=aF<9$hJFrZhNs%ju`oQ&+A^16t|)Z z%)$m{P}1Q$KaJqd{c=M!l1g!V#_-ymPvS{QtPo|-kSXw##;h(@;mL;JT_FFz@b}p$ z@^ZI;+$w18yFMFCFXVFpB7!MT)mD5LmHqg$i`aF7biak=QJld+Xb!l{FDgE*Ky;^@$;t$XfBG^Y(Aj&&}V++eOC1=A)eY~{%s{9RQ->0M&F zYXwJ9V|9A=(=Q~n4j)Nqo$sWnXhZ_~uz6`mM+ctTDg0f^=g$Mpr$ZFj zKr6y{QX-4lhx<&+%=)cZxwNv>IBSaAtBM8Vd5545Jp%*Pzv1lAbK;#*-TM(Tr|pXD zTXue90jH-fTwXO8dX9471!N;!)D}8;_2RLtuBBw~Y{&w-V?Xzj7`(u}K)?QnZ|ti{ zyN@;BDHL|*P4qPl!iYEOOo6#MwQmZ{+A}h<=*78v5t6Hf5^slVOubl(F4FK}K77LC zPngSJyvSQt^8S76!=5xAXItEs;GH`vm|L-SMPEU)9!4xeA>0<{JN@83jN)b|jeRm4 zo_gxfUHtpSHxyFh{}Bs$l*v_ytW@&($W(!@wmIohw+61lxps%HDbkx;wKuLmb#6UT z6@2xa{BNtOlUe;J||~6B=n)& z6{GJmRiHUvAtRn8;BvjrhkJjo3sZ{>@~~)ni0J+Kj$EQth8WDf?7#cw=yx1(TR=og zK*+M!@Z7m`A~E2+e)IK1v&72%mXYG3(HrW|3UQDY5l!#(pPaOASLzp<%wG4Jj{{{O zeV|;iT=udgV4@F6ihgc6nJpM278-fY|iYHR2ORKrQ=nKA0A=={ko6fmESG9lfwk+>h2M(BAWE zG7AJTK=F#G?|OsM&6^P>KXQR9|q*#>u z^~CARIa0?OEL-9TdMaWWkD>1yG1sc?VPN}O)k9E1o&oS zZYP$3>E!pAa!EjKb5H)~w#BKzQ_27Lo=q9RfSSIUbgt79S5PE(XpVzAjyP=lOmmC5q$T0a_- z#;$6?N_n7W#H+H7dT1EuM*ix=9ZD{JViWKb2VL%}Iyy5Z6HAp6#~RWfAtTpLx<7QYQW$!VQ1Xx=BvZf>Zp{P^sl7EPdQ}%-!A9R zYtUHmetq$$Bj}t5DJX`T$^7D3o40p8-b{A_Dq?tb+g(l%0he_PTbvVdrG(|0F~CJE z&p8&oQMZk5$X|$Fk&98CxA)pXqyg6x}zew$gTo< z3*(q!6dPP+&A;&5Zkd|(YXBoN^G!>fd2JOe-9kGre{U^147qk zVCWP_#BG`K$pq^wfBFLcY&P^F?mBVZ)qjuo)CJJILW=*#8(1Sv0|Vx2pXaNa^|*5L z+i}FwSh;W?cFACpw|rhC4K`3(*8Ta@r`1Z{kmLG=9|6t27pP2)=4eEwd*f+i^lNFR z-wTDdYLq(XEgY*9g;yd-B{$;`u>j{(k{)TwIZah5v&tBoVM#7bPKXns?-Hb*fZ!$>q|3sKmjxhLZ0E9%7qU+$VO)VP3&Eto(a$oSzU!A6b!L{_iUn6w! ztaZhKSwPW#mqgkg2F)f%S!IjZPVh%%c~iT#U?tI_KIARcoWii?0I7;*pt@-Z$O|<= zs$(&n`fPNBA#kOWk}X1>e(<>nK;OBhQ}RW9KfKBN>FSLbOw`BGpGp;=3sWG>%39`x zZzR%FYV-aTv!rPXnum9drBA4JXTCqiOby9cT*=aZ!~oPEvTG|^rlN<8;tsZSr_$;9 ziqGF2Eyir{Kac$P3v_S=5Y@4QWdG4a$5MKzO`?rRNE%y$vlKdjo}c=9`BKm-Eg`JW z0_bslF5d&OkrU%H6EIU!&}rFlkUVts(LPWGUl|9D=_m%W0|g%52S9;m@{LjYEq^-8 zC8La%S&p6pYwU~s7~6qn&d>KX|9CVw7Q#&$yd0BX_WvjVFW zj}{Vkv!TnH8jtoJSUc$YDw09I`_F0qpG&M<0RsvYtS&$>>r-OlSIM;xD0MVink$Z- z{O3N3C7Lz9L&T)jtv$_}oWay+5*LH%Vl~$J`1v#L_{#HGKnRx{zb)?}3R_b?pU4{1 za=xfikfR9RCuM32s+IG&MK7KHf)+`qFdgR)aF92s%Oc;2!`E$QlHE55HMefzH+E-2Ix*La9G3$;jY|jIE_}X}oyxqD9x- zRS@V`Xdy{!b(sP)@AFdoU1dAlXyCjCBM4pkn40?PEw^JdkP@VBa9NWn&OV@zzqrHT zVSqD2z4m#YW4L-VT7e~-qwm}0nP5p>+GFgP)BG{)6s=Cxg>xcbSO1pd1k4te>(&F} z#bEY`OH&RgY2^0!)xOPbQk1h&QYjF-^bMq-gVQ(x6vymaL5&=8{D@Y*cCyZ3v7@#5 zOrh(JC&8L+1bfkY{C^Jf+lsOosr8A0`E~p+wYg3;om?u+R*6Kx(j=IG>gv62KusGD9+OvJhU-q}uo8NrIck`cch6hvagVTQWbX z5E7g?^V{7ir((7cI6GWe0MrnTa%UJZ1Rb)0d7+%}<@EWhb*HqY&Fl%FhWYJw| zllNM_6&75^2diAZa9J8tf2lD=EyT6+&kU;(g72ksqgIy&{hiG><(+hSu`pi~*>rsNy?I zT>j0tN#c@~8Q#BYnmawp*H%pkfpp|*PCJ=il_0?tFnwx~Z|b_s8H;Xq$$&X{4glRD3lNEcKAY1Y$DR+xg7J5KK!EnN zONVyWqZi-$nmJ@?V3S(twNA(L9phXT`U3Y8=KhEMSJ6_>Bc1DsM2N4r-%kxd@yN zldYC>gq$lKEiI<@Ya}&oD1kiti6pi=tddhNE24e{BnafiT3UYnlAk{?LvxXnau>=0 z7*L|x6iFQNNfftYA2}60l}UShl&{#uf|8qP^W0dM^6cM+PuV6JX^I zgiB09P9Jn;JG;OFp2r0TGRyX6>Q}o;S_5#k`S=VV=~lvL7?s&|{YA&ruW}RK2ij_n z+EY-?d8lIRvMuA!CqzN9Y|Z1g;Q&ZlB$Z#eGp?gV#?P9kk=SWadcH6v-EXZV-FdI* zX`m-HL~gVi%zqo+@qQjsTwL_cb}ijO+j)|O$k5n$yP0B}S*HRhIAv_kl~qu?f$q&) zfnoW*izmM=CQJUyr9mRtkc;_YucQQwWdEqP0HJKzLd{&_CmJ2FhAGWm9ED0+o& zV1zq=N$7L6pi{_jf^E~R=nvQP+N&%~HdQb~00}Szm?kLP{Ie10=n9U}&pdy?E+jpo z^L)tmZfC@%qF{dCXr{xw1`WSyK)I6$$Un+u&gOixX>Tr^YZCQT4S&bp{g_*seX11b z=-skW=x#<4-}jkpJyR*RBtBCPBt{E4?MxAdKwYHv|3yzWQoD`CcY2baB zYkHTjot7lNQZ?sw7Oij&i&`C1sy9utJ{E{oiBcJUlMEVk*pr0B7ys12JVqFSVv`Kh zRYPBa@*+1RJ@~cwvVX>2m%h68C7)K{ zaR?9J)otxp zEtBVePxzFAAC74|poH25AmhE9fA=39Jj!Jy!kKr_1zB|>9A={t8tk^pkcI?kP#f|7 zHunNWLH7vy*DYotx`-Dqcix`N*}J}t+Oy#6hmRREnPC`C&VTiCH1+)__E`X_DD33j zE?Q5^(5(0csqhF>pyE9sE+sUUqY%+N^_7Ni`uZ_4w4a&*@wMm3D}+HesD+*%+YhJ> zj@y!w><=IrKkBsZai|AR0fZHFpVtf)O!h@ZM>X;kF9$bDwlC<{sPc@LBYeoi zwuqCa`<_PR>rM7+fwwo2bdZ{lBe9L;_q+i}ODARsA5Qz3yil?joQ(PR-gLZ#I(4#D zc_YAE^hkWD5|{+IK8bE1G(iu$+k@>1y{5^j<^6Q`m5$5X{Mv+4{FMVP;Q&Lxl;5q6 zBN|*5xw6||PSKiTsD@RDv3j+)aY{Oq1U2=|1t1qHzRfL^+~$^1DaY0C%mAC0qlcw= z^Fzlaojk58_!Vqc9CT^CBn^3z6S9s1gqLV_JNR-X5iev``+4=}u&;)yK~a|^s=E?J zX!`7A@Ge6?ycFT&VQKw7Usccx69hhDo+cVuqMenhs+x zE&5;PAEvl}A<6+fVKz0(s1Nt!&5UCym@A$~7~YW&x*MCgEu6TcAij8wL++-&m@y%5tCeCY?gu{#>zFb9@3uMmycqMMg15|qe0uu!$g%4i#-{9A(eWHE78A07w zDMTkDwYWiv-FzN{Uhl!=Ykg)U{xw`wB(dK++Ny(o2RS{YHQDXeTg;E8Vd4Y_@^`-j zjswhFjsa-{CtzzNtG@SAT)R#YIT_6p)d*1xAmPOJx86yqUwDL#>d(4KXYz5`Qih~Z zd!daJ8QobMFUf3&w4X8RuAy&Z=vUSTtuo}W(S9EKLZ6FvH|}IMB+3OpMKQhH$yeze zeVJ~H8%!-->(V4Ccj65m&s_B7sDaFO`RX|jAK;3JY9mmC$dt` z$#V2jtSA(D9IF%q@Fay|r5LWTKY#kcS=bky(Tm}%sb9_mWZGPiuF5pSOG~XFr9I*) zo!%3!zB1b$^Lum_X3Zyl1WsK~Agfvv%$e13UHVpIQP@~y3yQ=vm7-IOOJ$;yZ_E`x z+oGNmIj{n=3X(zzC5G0~YpH*1)?Y77y^*N%l$WY+1Z(8bI!4ovWid+hbSs#W+W@JH)X{!J7)Gchr@gS z8qfRxzwdRqx;#CuD}L_ZeSh!I3}~@B+_K`7SLziUvIDoA6N9wmNpGuyYxlB}(8r&@+Vk_d4vZK&F*{FT%TEQ%oK++YEhNUwnZ$FeNzOGjby3PWq z=8V!$7MsjdT`frgqp77ZIqZkuN%A1XyA+7$uAIBs^o$_$h zoLU~ehfdw5#vvEv1Xs1DR1$wqO<-JZFJCH{60F-gHfRdhkOuQnOQ*~zXZ0(3Zjme! z@2<4>oYBLPWAAAkL9T(=+sKG#<}?bou^|~Cube%wo{9WY7T4AHqSLdHb^N<;e&qnH z1M{gc_Q5al(BGRR@hCarUoY)npcgu{fQVD9f1vqN=_Dr1;JK#=bLeGeYoQE)W}kc8 za7hjV155ggElf?FVS|lNQ#&0%iNy)VjOdgS16~7Nhars}E&HYz4n(FSa6+R^ZY)Wc zoS6s7(3sp8j88V<{{=UkNWS1e5Z#sp1=Sb^1vrv#BFfF1 zJ8+JVM`0Qx8|DmQ4Pt4R0t{(Mnbo^}w{~?hnL`n~tUER!(5bQpOf7O621CyAy5HlV zE$?BBI?sF@MIf<-T2TJ~qkKmbLq7e!uZpNptbF>|@h_KF6F_%ty!@dG3pm}?nP@d6 zfe$5NVPOFT@XQI;tIin5l^)B}G-9;ZxYbAFmc{9s_~KC^SA?9r$GGbNO@Q0W0o^Gm z@x9c4g1Kx8MPKuT3cKzzCtuUJOvSa(xbZ<85^GdLUg~NMQ@4LtI`oOU7sUt^l}JVb zX!~N&s4)yGU8}yPffYp%KESji2zYb3S(?v3-QS*To;QPHSJ2;qzoq7=A-@T@xEp8h z#kl)7oB+3-?ZHZ0Q9_cRrmW0=t3y!HAxK~|oP&jadvBlag}xwZal@D5)ivmug+YR} zDcftpzgHKLntbc(-z_aunPzps!ZCwv$!SzYu!S}FKM9M(comM8L=@KtuNQ$}I4%br z4#cwXUtr(e@FZc{X+wz&C$j;^hhDCICzdlHl483x_oOOdjMR5nCOjCNT{~{xh$QOm z1p3~4moD@3pTq|mI9006;rWt99AG_3R9B#ZT{w|!aK7V7gGWEI*JrkM-);b?c%b~# zkc>oa%jJh41H|Z$uLF7oz(-F!2utKHX+SQ!Sd~cG8l=9wUzfZKQc-VBoBNt@EEvgW zKI;A$&P_ZUTiy4uvxOu=(s_%g>e~YC?QR#k(^#v?|%Y7 zt|^%4n4OM|G{~JF?K)R(h#IM5!(%`qIl_%91NhEvv23oL8xVeJaFzW#sPY`I@#-34 zl*=1@=6hcC<*6Pl9OOWb8UXxBNfcyB0e*afGW2su^zn&Bs52ahfo3U=g%{);nR{>k zFRmgYMG@QU!EJu8>oL@Y0exh4GdW3T=63r_>i+*lu9Zm%tJ$eu83rA|3yv|SpZtrk zFNG{)>mDDWJ+ZqE?k0p&+rw~jb-I(X8y({1-=|XMUtp|HtUrqcJEmgu@Jlq4L*6q` zHzICU*5Sz9@i|`=%I?EiRr$WN0LKry?zwdexcn3Lzm3?G@i?$g(dZNmb%DX)_oegR zObbSc^WCs;4<5R%g4&+Jy|X~w*C4!K10*caFt$$EeaKB5a=8GiP*%dDCv+7>m*yz< zaD*;DSI}jQ7b&Cr!sO3$0^H6i5MIpSU#@@gBI=Di^ISY^z!5k^YA!%>!40p( z!9NSe$Q#D47pqo@yG5=1rdgerGKNlKJtvqwCKm6PLq9?*O9{4`d>R1C#Z-SAQGARf zYFVuo@PEIY^UmMG|MS;MFY$nPqD`aEaF`Oz;}^k{gA| z_ENV!md7FcZ@^ zqPo!`yWM@bZ-_u0lK4%ma84ak5w)=fKn){W&|{wRD>VyxL2u9;i^T!JD`Q39L4IoJ zFBYI=u|OHtiCMcBcedfx-@t~WPrwd!blvvxU+&q+6&6^l27DqiR3aSeG3Dd8(B{Iy zLBJ`9UVRcu5%KaODbG%`BY(P&76W4@C`aCX@5nsYxEt; zuhb5^Qsp_#8FY8}gG&l_zF84ZiM9-weadh|R=SGnBTPS1oolIVo8bMDYYB>fRnnOl z+hG_D4gZSB%PlMGT39S;_wdR0^|(`MZYx&3Rf2UZ+*>&;V_bTTKFs_2?JH+{6!Sp% zOwtFi{d=;&^DaP#GdS$_c6bVli)GG;ipOHw&mP&*N-H|-;@YcbZvXb`&)kK%2BbNP zuXn#zfbBUAb`2y+07+r0J;=3eV>B=O>WS=0s$&UL$&b#W9OfAuPQmN>I=WaKnw;HEuzRPb-``GeA8F)vd;BCAL~D_`#|pURh$>uYJg zMa$-85~ytVpwHGGU|Z#>h#Af1mcz7s)kCKBm124Kq7Pkla(|v<%boHu{>sSY6wWOev<61fVbv{2ZF1I zEQQ;xJ{~1+r;-rE1?fiy`XBk?)s4fB*Y1t25II7oG{j*Hk*4lb^=B=dg-Zt?m!8`b z>(n;YmwRQ9=CFGa`xwZ|`I$-t#}e4Wp6$jcbjxxYiqK*i_tuu*mxj|vLy4~YBya8W zhmbcj#r$6MVQ1&cnRUhPwY`qYB@gkk*6DJS-E^I{gZl8Vy|{JeUjc(Ii=C2HPg@Z$ z$B);3G#9>8^6sO9DR#~(fk^x~cXHor?mJ zjXeTrA?IF02FV#d3BUlIYkyR{`8!lk9d`7-dhe0VV|1qfx;nM>cwv^FCF%B3P=%81 zYle>(t?3Ccf2i7q+N-b@^jxLMI>uo;?`u%D<>_;T@5!>M2quO0ser(xPcs`xV?L>Rkyhnzx z{0ZCdX#LTSH-$h0peC#F=_G>gK&CFbdeptDlUi(&(M>vy-mUish!R4sUUMPYnfybg z-0Ns05Bty~=O!c4rtYL$$?We9jtc^>fNODSD=5T() z3kEiu>cm`WK4z(vj|aM>VL371@=d2vS=DtkUSf=zxJgjhd$K3{cSVMUU|m4chBW?4 z*Q6Ngc=;Ffeo#p0-L8N+PwuIcEpj+k823H*A3g|H2q5V`}8VgosA=EL6l@sjWGZgr4XsdrGBQIS zkWt11Rv7d7Dj(fAU>xf!^AvWl8b(x_9M=4axvS93O$RIHNp7U?E=;nka_%3ss#3Uya2C(CJP;7J%VgddB51#>X-!8dvKvqD?VQM)8n>NTZ;2GN zH*#o6;M3t8dZ=%<4KKYtLCrbP>ex*tZttmp$9V12sf*9g4r&U+Yorq?$*;|CEv^R^H4vq*O9;;f}(lN`=Fd3@5sDXN-Sh zWV@=w3R(!s$gZrebB7Eq-M^O5_6SRu48eUS=+t}N35NP&P*RW@hibbpy&UDc+a)*= zMULG3c>3KiUd3QSB($~{FKRGUh1E4%0js6HXd@h=Of9tx$;grcSH{cSW1d_+d+pfYw* zimLrqLa|}bh40j1&i*e1GuUuKbEj(5e#u%0!+!8%N69%l`~ie*Ki9a}SWdHVWBs{u zX+o5edH2MiOl9nfM?r%x^==I7~LgOOqZeymm zisZN)ao|yk%P-IB$8a*rVFKPW%pZQ)ej-gyp`4nl>pCActroT$A+y=j-OY%1Z(~}p z6`o6sVwz)T+!SE6QEbk|qLn^kG14Oq2tv+M)V8MbP;)Rb)Y80VS~>J=22a@$_Q6lN2?K(ksj_XVdKYzsTWat&}r_PJQ;@h(-5hZdfbg1)UUWtS3Df=3Xf`QdTI zviG-g?%sIfo*B=9-avTSA?QK@x#(dQ2d~e#?K=m(%gM=EK6)Ao&Iz4{ivZnlW-9y> zX?t|L;E-6b4I=VJV+<|bV`HD`{gW->fRu{&>H;EF&Qllv%{3L#f|SUh&=LXI+f5Y3 zLMZ$gA34<#0L}DgWzd5l9?9y6KPC=fYuZ%vurLePiMNV#gsQ zLzhzg%zm9HBCqlHj+a@Xp>j%`e-c8&kl9@cI z#W0S&bY`js!hS0ADa-g_Ou{~TYNslooqttJp~S9nvHZBevBBR?m1C6THMAUhwctk+ zSIc|JP8>AhfiKu6W8WjGKiJ=}KV_r`8%OWa2L+DBFRLAb?rP8VV|&wT2l<^DsHX-P z?<|A;mLnkHlo}{KjNL?JHV2lrdyHM3a_uS#a3-~c*w#zWU@xOGeGaG;sn@D7xcq?v zAPQc8$S3F7W5lWApGyC_(RU_(M{?w6lGT-J?w*2^N{|)c^Vo?ml@aNP+c5^8JU^m% zFUE7f^SDybEMtH3_Z_vF#?zxw`&|Nyi2mu;-96K(9vNzf3;RF)YF$*U{f6!PU1uK1 z=GWAW1DQfLe`}2T#5I|D<0BjX0>26)!3%Fh5lyl6*6QQS%YT9x0c~2BIraRU%PlVR znRyh2^yfZ3SW3)4=h`xY4+swKwoxz7g4}IxY`mqmcBHibgzWS2RB1?W=sx0-A=T6B zs{Zyy!S)f@qaI&0Z?xpnD|v^0ns6=)=?grj?vD_?^2jfaNa3DHPB>kjb(%`X0|d}4 z<$plSOoVY0^}v*BLk%_L^->Y;&Wp$+ZPm|Nmh+F&9c3Okjvb5Yeky2mvy2=!CoERf zEG-2tcD5Yw?Qp>5?d{gD)k|v^8i@dcYB%dLy5<+w2t;kW2UB~o&qS48;QEzz>ka(+ z{LPl8g%6rG9yter=s~ooH2O^Ao;HG<1G&PDUqsw3Q+xJ>$a&dic>wZ9O+@vf`%@%LV1F z(h|4*0JgoeiFZw`2APV!UNvj3zxs`0)ay~qxQDy# z)4LMUG`GW0U-t_*zx|^FkP?vA0!mmkfa3qah2=`vo8JMopjr(K@}E2(FJWY9dkn722m$*ONt zkHe|>;DX$|Uc~v_QK;nAz7_-68k@pwN+GjrHd0S`xv3227&Vk5pGxx?8Xqa)JM%@C5=0&ih2faMRN$?}Qnit-h+P1!W{rW6rl0w|)HReH@Q5eZn z3}mzW?tfV1Bvld!Q?^CA*Q7l+3+RCGh%X*>eR^NNg8cb1}redy$j1EC_EB z6tL)3Hecye=CH*I`U2I8XAjFdpyuWgFi4=H*=OR&|s?_&ioFWzPq+s)Y0W`?Snr+s(PIIsq&Zf z|BFOBMUjOcp@T~)gh)v-tq(DL)#O%!htns0+2GLH?Mtb#qf?Qp2$5P1DKrRyD-8(S z<6f{i=dt4A9@6ow#`{i+Fc3DEKQ6wPb*Qybo6BmK+bYsb2iHFyC)PoJ9*ZGrlU>Jo41ac@zm`NWAD+tM7oa0QEUeG%S66)^B}*(gfIVbA7Awm>-VrzGM0D zN}-m|i;v&vCGi+RRvI9c06E#WfL?kp(!<_jU3}q2)LyT&1^dev8s%Cu!X@0O+fA;V zd-WS)>6dl$jgz-32ToJvxEX0z(x1HP@caEcH7>^gmYEN5bo7j?JWUzBdtXrq>{ zS&a-vUAb^}RnBi5I~18HSxipZmR9lfX25ULL47#&Py*j^Qx0>R$n~k6B|tsKmZY-X-G+Fa0&^0yOD}h*7AJB>@FjX!vQj)r3hC(}0KcT=y||8uX$vZfgqO?(wF}>7PY_ zrJs>q$-%Oi|31SsK;{RF1RK0#B^?A8J-K3O!?m^kH}Eu0I6(oSuXw5_fa1-+Y(Y;I zEOk-{w!P`zUOo7a>~`TLt<X3;HnrK#Hx_*c&_#={gT+}zN;FLr zH@!g&uD`RB>*hng)F@LsWag!hjf_Il53b#M@~|usP|-?)f`V7l?LObRv#?YbdS{eG z9NliWS}y#*s#&P`{`sqqQMk*(DE+Mm=st;x)$?!JrRvy2`0Jvqvmb&c zB$YfMV0e8}rsqE0`$COg1i_@P0BSo4A85(ajEXT8r!k**PSND7M$y;%eK~%^+y=JR z<2VD*k`KVtK~&HE`BQ$7iOmXG1gU$g4B9gQ6#*(|75Nj3=BhqOKZyZ({>02!CWW`9 z8Y&C%(i6MZ(fvy+MN1w$V+g*#25ZLq{4ph&FaTrZ5WZm7&x z_3jbGhO}|ISJW?pbDs1ECtMyXYJgHt-vsdG!PQJHQ|Mf;HdjuM=BmKm6jHV#%UW`O z=3U9A3l*$^;!Qzz>iphAD0VS(g~d~Xm}aPOIL1*!y(^I*Kw6=@tB^ri`)IfGI;e=- zcTjI5d1PO$HAJ6&+5!%(>W^t5OTTw5Z`n{S`O!qh|2?R{jy^|4@tds!b>AA7sOW3A zKNJu&41xXu&Q5itVS?w~5eqzqN5G!^Zwck0_I3W<7%u;w z8{T<_9D7N|QTs>^IoDL?%+fnw-`FgA12b)5%5 zNH}z^4^km&jPM++MwL1Bp0br20rkzlS&98I0r-0|hoZtDx9y zR?fdCWbV7AgIM(!8Jnd3s1}m@VRvP?7e$FSl$Z(t_v1J!{Oztzz7W=QmxAhVARyij z3bFv{Y$IS0St{+nyg^)(UwCg?(gamSV6t!C@dX%)4kxS*60tT9PgX^ib*pS#D)0k5 z%@B0KO-a3N@=wiRUiXd>{0<*kqHl9Nj|WD78vPjeD=hMm(-=(cn#QPSP%q`Hs3BR6YI- zG6@L4lezrBmq{U07wW&s?4c=L!g_V>UY`2YMM$rUDF!dBzL}|M(#1J} z#+k(-8Xo@EvM92AqgxF}-QS~T2SgdZgxM7QS<3i*4bx-n`wm7aZlLt(HUI`P4Cc;! z7j?uQYl1B`g08#+nan+_gZ5zQ3MpDjbT(rH2#VpD?SS|8@t!R?-?&&Gy*-hHL+lso zA1s&SemV|Y^VBL(S%=hx)))!RV`084_Gcy;%{njf>% zJE_uM8NQEvrW)k?^Pl^^G}mUnAFJWld)=^e%vt|)htuSz2F2HcAYMv==gE4tj9m-U zv^ln5H2HA%c$i&Y%8D@40AeV)mTylUW{1KfL)GmP~b*!?TgQUOWl9a9*R(%S)6*QiEFqCI!CF zXOGpm(1&z>i`sw1I8?_*rSZC3j)YgfkMI*>pDhpGE03*dAgdp*#AoPF9Z7pf-_}Q6 zBdi!d?FV29X=4}~u#(?A8n_NT8{}((KZhvDS}3Gg{J1ZJvmWORy%NgjQ=}PuB^w3) ziFc^5TKGsk&wkh}h&n?0APnVJ#XU16XD%E~Q#TB{aZ9PLTcFPRip;aZ93F*>yA$-u zQ}^EQQN;uJ@}dAsavarrxF??oFlUj=33PNork!ujSDt(K~%#68;7$a?UL{^@cqDR@uRe^ z&Yi(s<*;Riln>=jy)PUL%6#43UL9L5{ffZctdYLDaX8OL+E6wCU87%{6sw&Fh1be@ zb2B7+fH+pYm&vnhmiXl2diC?wdR14i1H+duP|?wv8`B{;YN+fK_<=tufT~Vrl8L88 zmD?Yj`Iu_x?FH)>sY=;@!Z^X0=ABMP>H0li(5?OAzL2c^g9ZajD(duh2^yAlOuMB> zHk)hlvbh|tG9Te4(?DjpXqc|_)v&57#8JEdk_uhf3s%?Cr)4JbzSH`53$Ia=AlnKl zQq?V!b%aiKy5|H)^g_MD$hFvhBXhq~Vqme<>j$}@eMA}kGACPu%9x8l~V!M!tAx{aH zcsXZIo>jtqPWM$bpk1Iz$<`#2OWBuQR>TMZAV<_}x)5@&r_DDGj83qPcuFkNx?Rz+ zh&v)6b=w*nYDWA$A9*l8IDA(!_GD)*v^KeorfcFmYa4uu9n>M>1aF3CvUWAYLRQn+ zD70^J!nTfQ%TwKG$P||)cp}{9%@ftwFQ{SKGipcv8E|t?$R+!W1-v7bQ5in#3^k=! z;*2?uoe!EwP#dKrfVY4Jrdi0SRLVt>e@Y8&LRYf^#zQM8zg=Y7i%!ejQ`wCy?<~^<&KbuO>mBi! z<5TU5Yr_2WG%bwjmxTx;U^|l#-1C5g(`SNdL1Vhfn6(mg}aKV-BHBd z&1hr@RTH28kkTB^FwhJVy}nQJFgUF!7oI!RtP7em+usQYLPy-I@tR}9e+8_ThZn32 zsg@8m;fG#5R=cOTa+N#h-Ad&zhBtGC)$;`DQP*;>e7>OhXN4X9F8hsi;{^=6f}aXy z9BX5xt10f##fUL5G~|~zB{U2e`}GQDlK#DDXs}G&KNEL1JXJ%?ovD`aBh8K@^z;m? zf4w@Vy!kL*$NOe+g!)m4K=6{s2MeY=1H#+wN^0&$;O8Wy_KFJ)s7l5fnpy zD@=Wka`bM>9RJ?X7n3=)0F`&`yh3GphKFX0Y?SXh;PnRX3sjR{6ExSC8rFYVOBxw4 zshw1N9Zhv)LZlFVeU-`!Jcu(y_OM${Y1{0L4im-MSVnYdBdr-+WjAImjoiY$aoT0# zAp-&VqqH5(L?vv^MeHBJpWK{moFFH?sIH5?7k7lnpgW>55yCwyEc6D*_CbOcYF$?jp!TU6~Xhu(s|c1lM@E7wpE_R)XuTu zyOK9sT%e`wu@+u~+Nr{Q=%UK*@uNTxYOFbV!d6jVM>56mrZspT^sbFE0GcCT-p*^^ z;Um$7c_6uAW9y^j>Aa;EfG4xXMRfM0Ap-YwXm;;8DLLomw&`hcw93q21EYes!~JX| z=ZNHGimpnhI_WcA(jj)L#Cvga7@i4`tD1aCpd;7SPwV+6Yji#^gC1Xpiigjo{9H}( z8UWb({`wX1;cSc-`yhD|t6kShV3}er3z?pg(jI1yVA1MfvR!owGhK0c&ebAJ!&z6OY=i`-Ji{ue$&gC)B+91Bw%c$nhBFfyAvE!cK^nu$Psa@{OBx#mx`K|47|H zL5sk{+%pS*b0;=!D1>``++Qi-_hT(HjPUp0cy&$5huw`&t6i&C&QKWp6i||mCe9x- zt1xY&H*voomG<^~oqa1y*y+56OB6ZRjsm_|AO2?IhYX>ErGbTquC2&Wipsvr-s2yp z{m|gjdi7J3UUOICLsFSAELIQ0?>RWtGf;l`?k!AqKW$5@jzI|~BJHV%*n3B~#PPYm zVy-!5F7r^O-cV8hjpy|9<+=xM0<~7VO(Av@kqp~}lk7K}JlYBy=v|03!V6jYtL;w& z_48FT=1y%s?v6W_Opuk#3@^1WP_;yw3`MPhF>TtB?6U)65b_00aAFNzuwFgk7j`dE z3cK$cci}@AU8%DS79voPvzGLT41cYLmR)^TIWlw@yhjpj{+}z;yx{m&&kR8~Hzqbz z*Cd@1)e|}s8K-B#2Q;(dFL%QX#h-o{M4&QJHEA3$dN~Eg{=pR_Ub*rhvUvL{^03tq zeS0%)dzzTkt46$lKFAcq-N5ZO$;Yg`kusvqoe=h6kNHs*<`x#ai-;uO%PFk$LrAVG zog$Fp2f;j32^C1Oe-qx_W71K3O=w7Ggyle>ql&nRiI zsLTRZRsPcScID%a&hP$~$TaH*y9j*;ATnH1rVEKwr=eQFw2!xF3tI};7)&tAKTr2+ zioKZ;@+Q)6}~-fKv?=kA>yZls1dhmdcn!KiHgN5p8#Hl~kt-NYRE4dGILO%+K31X9 zr0JPa4z1T+*W-w=v+h$IbY)5j?9lNVwof61`T{tkrA^F!VESaE-wDbbLU;)m*T9#k zvJuB7g&Ixg@PkaAh>3rQnziS-alHicYN*}HSh9;RsaJB}+0E#L75tT;(ft+Og?gHw zNs5C=-jo#)Z-NS@{ovJv@>A>U3->JX%1pJx@%m=rJ!^q(AAs$=4^gtVsvM1qsQFBG zc;2cdWz&PA%Rbmpd*z4VNV(pNLt#1{s>=xSgP#OctH)-$WbJo_C@+a-*)GBTgPfQo z)Ve0uf^@d1vrFxYVv45)t1EI|-%5r%vySS##f)F@j-MCdM0KIA>H@W@D{qqaX&nyP zL>8x3bWa2K=(3Ma(Ag{eu42~RY27o6c@UvAKx;o&!UGG!821X>*S?f#BOu`6k8+my!OF-IU$9OjADHm^#64OX zb-BmB_BAToYNmE~>Jg|)mYi|u&&CYj2j7hNHZxI&t86-~vj;(3)nem9X3}wOUkF#* zjJ*eW;MzSXyLO|E;<$= zFTfz6CbP(c(@0w5`T%rcm%BZ+EG``K0>j_X2rntSU;Dd0x}UWX54Fc*Rint7JZt7? zE%4@1So6fkC*FFBH{5%`CsJ~A?=|{2;s=4Z>M z9(UH?VjnoA9!9R-R(Yk(cw0=q9?i61h*9YM+>f1OHh&yEotic!X3MFygQpL;4n>A(xRf8-2-p)n;j^sL7RL37gl0C^=JVA5}AT29+JZ$yZ~iZ|0+X z^*)NqIvj<3p~@b4z#sE}9L}l7BXdAsqM>d4JD{3oNAapj zaFLLOIPQXqu|h6~SJo$9Bs8xz#4w7*hIw!iFf8ThYT8(-D61J3S2%tT6_4QjU;2&Pw8y z+nHZX2Ni`m?cH};Aw1_NPT|9AzLkTlq?_=id6yc$0V_lb#8q}*9OzZ*gTz6h2N%?< zf9KRfU@9$$$LwcA2onA_p&dCN5-LVT2CiY@Uk;9dN=}U5O!Jm|^_EHSv;yo7Q^MU5 z=UjrY*$$9jcAV7Y*7!$^HcTVK-_4nZwG9|{qw{npqJSEB+3DToAi}cvutv`X6<(^K zO>7eRwPb~8$>H+{(MKtZ={j!nxYKn!VI%TXFn6p2WZ|FiI8PeFstpgy;pBOMw@?PS zf1DTMSA%JQI<3wsePsZXjZDqb`%J`=CqjV@pQUHaw?*dwibM!C-fsvdPMR-bWiMHW zuh2E#pDq++gA=nZjm6-EKMFv0Xib-+$$XGCjbeP*VJ zEAaSwkH+Va8!FgPspMMgXABf)nJ7*(l{Hv%Z1vjn?BxLTZ9SB02~Rr%Hou|C*5(=vdGe#kuQw_U+r-#@YPKl1mvMWxE=Dz8W&J^=&Hm)_-J{K8&ve(pxtG zqBg}Owq&RV#c+tyY%4sgreF5Mf1qgJ>1*cQz<0|hD#3@+(2!Sj>vEq(6Rb80NY2aHDBKD;u#r*7O-t0)^(x>xaRXMj%1jn- zvpZ@yIn=8w>rjAd)mjth@D@wChVop5+^|kGaWl=W50C)F;iwj2Nh=8Y7c1agFmA4N zRh#yiBDms5qgNWrvPrqz0Bdq%)!9r$j#U29paZAR$Gg=a$QkknEX67R%zVxkmTBEs zTx(~YsMMwC!N}9v{TDX5JO*->I9TGiD6#>yG`z5OsTwW1Q2O_={CYT>8h{F%59fIf zmHUC(tAUUI^}qic#YPirQyxZ*^${~PHFQP_D)(Flr3@pI~^5}hk>{P$cpoJq8a)-)f z@Il#ddO%SKXi4*mLhX0pJSC8^IrIsHM53pu%{{7?<@l}Pd~;C;{2?;^$R&%J-rnT&U9AN^UR7mpGvdD4 zVz6D?_VOs+aVC^A7~UX8S(#qUH;FXf0F#> zG-2=|&#qx$g>(b=7KBe1M?I^!k1cRe>Uh!+VU1F(NB3ZcncZ?4!mvAq@#7#NVyL4P zx8I4|UCv|;laTm0cM98`FApMpcS0rXnDRBAd3AL=gd0%YPo0g-(VrR5H>FZ^(Bt*-&17?`BF@R&K$)>jLQwU~nNRbnz)wt%$55pNXIo|71 z#Lqa0wGFo8a^0D3vJ5pAX>l)m;A+Os_Z$n*Gb1^g%Ka}gA9|bLbEbtk=m(H>N3x;q zfxn7}iR~)I;=^~f3-Q0!qPhl4g7K-IGtilPCiUxsKMV92b*N`U+I-#NB+o&8MQE$R zOx$)H@q6j4s8+^5AOon`edvC1+{mNFN$P_h9TluwMhFO(0Lj^E*AWP#@$2>O`tp0N zUhe~fx)cv#&NoKe3aB-S`WJ(CpA_^P?@9Uoym{zU%kMU6tLqc4I`YDD=*DS^FJKJ# z*EFZV0e*qj6DgSwo%>(SI^3qImm?sU1s-ElYP(l%;EQXY(iHp8KD}}8G^pfZMmI-= z0bToSSTtNrgApqt4B?dfb~^0ICP(XeI`kUuU7q8Em3kU{@pa7kuuVygFD7Mq40SRd zYsKm2@;~WLME7>{!kBu6-)~u;DCbyM=U{O<2O`{gRtJU`>0Qgd1&_==Z?AMcWD~y? z5qLR_u`8@qsL`O84e!aq~OHTw`CiPv$&HE7rip< zW`*2p-2IkhdF$wXiIJWgB;sO0`EKkUtFz-3Z&{ARfK!`VOWtJ?@@vnU)aXw4=)M|X zX^Y(eNl)~Fn@%a${%rySOo@&)$Yu8By?g&@(kt8d&b-o8**MpAGc0a@e;fZ#h&8=~ zI}O>;LEDX*+px^Wf}r&Ru8Q$H&dD5TPM{Jtz4;`X_eApE(e28zRz@U^y?J}&@_y;N z?PqSno3qJg?rZI)U&1dGJ_R>l{k~*CKt`#A1+G&*ohpN?d~Wu1>l=27`bOk&p#Che zU3r25;d9nri0^%xqTG~E1^PU^5y%vbnxr>?M)bY~cAfW<8ENNY;2C#{h4iA*Z{5K) z^*?J5N1Lwt*{bbo7{1KPl0N-*J9C$K%;y!a8CVp z&eP;%P8$_)19t&c81k*rEF?)M3Ro+vx5h|%+&X9auJe^V4l(7yIB7o3mvS&^`VVGxZ zYC7-8ata=~$h>s535|RvvcQ)#$=I&j%fp^Hc%08^u4eD&#^6bFeUKNj#eWc4R>+C8 ztK#o7Ih@{F!){Lpa1H->9-DdQ{csp!PzCA*JH%Kw)2W_3lZ5l?R+aNz8v4F&52}#1 zu*Jy{A;Jr#*IubG&*{S!7F?F0fHK|SP0gSKf`Obv$4!tr_WpyuWcrV)D?pd4J6=%4 zuY2d+E8ymP?y$fIm#l%Y?L`XJQ2voUgN4Hs>I-@Qxzta~@j?FyeHe!1a#sd)bmF1h z*iXBhp$aOME&X|5tl5yyt(*_o`g&uJjL99-xMeo-iret*J=^DLnD0`8WcNRQ&!7Dv zv{m7(e-R;{7jSj6QywSKPU}JOwFNn?&?gweOif z9Dr*N=f3Fyj;Is+@E>`>V?KkBulSD2InMQI(Xz@b?ewEa3E2D9B=MR{;KFLSWjF?c zW6~ST^+%UH8#r*1AiqDHb$QZb*L+oQQ*gir`!VPHYHqwIJtcV(L~!|nTESO?{15gCa=*cbZ!HF!3%mCFrPhhgh#n8E z(aEflw)gls=5B^A`sV8zJlv%)oj-?ezix7Ui-uFiF7NBfcUu;LYhT!wK(_r*t?v5V zLtS9Kwm+~b26mjiCcvC7kb&K^}zsLF;fmUjZK*+q{8CA=7{)4Q~j3Gktsub$*`%fEm2^gd_Sl5GFc zJusQLXRerUHwnpeRq_Ew$#ED@CA>E|f8IS~-CI=tek)!`q+S5BwN!1FU`ZYD)z(^? zHrDtq`%%DZ%D(~yJ{7OeKYR@6QMhc=gs}YedEo#J_(vcqW;dx4r!?cjHGd{z$p1((;#6kSDa>>#?X68Qhsdmfht82(|&_|#xZ+N z8$t@i~m`jXqtP)u1F?sd;wK5wx%u z{bvuaZ9=R;-I388SPy?NX)t)1@@!s;Rg{YB?KGL>;TH^|dqbyUt#T8hdZ=pGoPpRa zOCrp|n`yJ9!D00XYT*ixO`2~H&BrBUEVwW0hPks>{u?zDClwB3^y;N~D1&!i_j;dD#1f+pSlqrg3!2 zzm9?aiJ{^soH)>+7Eu-^F$)zDE>Ex$q+W7w4L1uZ!QB#cEk+o8TBb)*7Qg+HErTtQ zMZ%UQrBLgXa>R99kF~DLo#mF^=X!URNv}ex2JgyhtR9xJVWKRB)8Eb+gzwEMRPzBNspK+(SjXK2~qhy)`MxUxc2^Ko%TEb zR;Xq2!aWlcIH_U!m(t`qyBQkL6&gcVglQ;R2fqjzB7WebP+@xTYgwuh6N!-a$1wXc z*+rmY2@dO3bhLSR&jB?l+G@=YyoK|*%S$EQ+p_JA?Qrfa`h|YOj61Qo3A^V2()N%% zY`sEZ1rLcHr5!zEl3xhr=D~Al0&+?<%z$)`PyK!|*dAM$L_quHxl2}zY<)OFI!>Cx zpNYL8GVRk`nb4Z`DI$d=a&rD!a`8Qhz0K2s^;FB#x06`z@{%-uWb}~m ziZr8kFlM6mp>6w9Q8N^pIa|bY5}1^UG<$P`Jn=KEa&E*~kTRINw2mXG?hSOD0qahQ zupSk>tGf;UXx@I-y?^6ZSHh)Nz1;#@3EefQm0K35>aX%=iM%;X-=~#xK_l*;GmiNI zIQE3YG7o>>$|4Qbxwj1{V0UJyy-L5bI@D`mL)cz9DUAxQ|HT4yQ`A8#f$gQ8E=1@# z7_xBe3DdDgI#oTSNor<$f2>&Um!uz)KV(G>5q%PF%sH%^qxv*-L}=FR*ly_TPu^VP z+OzqVjg$b5F?2qalO3*SC2RMKtte3tq*aPY%QIDusjC8QOm|>kB8j|CG!cL$W)(f_3r^=WH zXxRygv|K-C5fC=Y&PoyVvBYD{=Fy^%gW#!Uh9J}zD%ow7^%nkbIO5n11P@_Yk>Y!m zr-Y3o=3EyPV~=v$_ZSAXQEA&ViSeV7a_@JVUKE(hj>|aE)5ij1j`g_@TaO1!4GaW6 zMDo3ym(je>p!^l&e*$q+pIs0Tw=F%^O*V5gsQ#*h{x&Fo)7Ccoa7-O%Ao>4)5!(9d zT)*EjFw8o<<(rErW&JvGO^^)2iBs1(wO`qFGyddNgO~IfU9Qt@;TJTD5G)@0(Ih}F z4n`B(LHG-s3;B5L;o1XJ&tN>M_9Me{o$Iz9_x&Nydlc-KTpuuA?x2}?3@hZIljEhj z&>?r;N&TwdjV+7X>(#fuYIiTZ{&?_}^zBwq>^Mq=!z0Qpp3GKZfAg$Hv zU_FI?n*HB9RN#B9R{V^?bzDh(9y?#YWdc@feXEt+IC(XSZMBug} z6^SP-OVbfq>81Ze*IPhE*{$!x1`+~}h{(_&A`Js7pfpGdj)-)Fba#VDNu#uMgLHSx zfS}SfbV?1<9p4_~J@5Jb&$pI~HH$S%W}at1d*AnUU-8RPa{eMnLS+Qu!tk=aY9xphg@wOCo5J6Zx`as$wbQ;dx8av6jaq#IY|*kxn8NBh zuqc6St`ab?2S6yEQ9fr|UYfEB+Sh8|&~x7qA^iaASnLAva11*d6FA*$!z%Yxu=Z1X zL>~p8ihv7@q0t&>@H!~h{V0JU9bOZ@O=N0Ye^`&!ShW7d|}G1=oA-Ee%m^ zYfwGaQK!UR$Y@3}=vNCbl%k=iVqFM}WSAEOAq@Sgo&Pkxb8REKD@y|kPVPD~OgR{| z3--I`&pz*bVm}Ur?Y78@T-+Erk7TO>rh9g~_r0^K zQ~$N%V_PsLG}y;K8lTa+|Hg$$1K+sX7cz8DT=z{N3c6;RIH21dO=UuL@mZyhA&VFn zxj97ky|zZ(;K=Q}bh}&l+bC&ak)(b*To(*R%!WYW7!d)>nuKvpSJqPg{n75>d}jn# z{a!R`w9ni+Gs$M`6GHIe_uYR6d`31`IG0H}F1@((=P@)=yn@yl(6!;?@xt!3yugSt zuhz~-M@f+SQJBq_KEaD1@Z90{B*d4IlqY*mF7l-Hiv%g&YwV7*R^rB+JGwJ(U(j1) z+h@a089n>2CK9wpWNaJDcRf>C7SdRt!(WsmHtu|O{OS(dxDO#53{(7)VRJW6ect<< zBc(J3rA~5!tb904+B!w!KGQ5LR;cH{ZR1*D^tY=R_ZfSM#mUJ-NZL*P%< z@QxOLT+;k;E=y~~AY#A(`J7z;C6`ARS^n8V!8cJ=MS&;4_V5J%Bla)L4fL{pb@K(q zzwx&LiRMYxER7{=W?DsgWPZgpM?c9y z<7~EqREh%O4&B}ZA3`PI;TWGT2X}M~qp9c0S7(b?v3$6WLwWX_9x8MBvI5PO2T?*? z@9o%fuBIgG-*YO6n0MBe?B0L<#M6*mW}%=xf`b|DjQdqY|A#gW$IBronqKS(N8PO_}&K#+&>mHtzue7PTRpnYC z8TM^6Z14|E>Lo=VF6)B->7U66c%hAPMK8=?kzBE~g~D|M@x_Yn0nUEFLy@aFd~w#FDm0JdYqFr{!WG2(E25V*C%f0)cD#32e65rDLXmoM=p+Yt zEHm#DF-KcW)jw{eB=vq5z~q_LwnWKV&{&&SYtz%wV6Hl5&$kFNuPmbXsg4)G73a`2 z{T7@2Zo4CWpx4$n1!wM~Xi2bub6=k=$3TflJSQ9)wyOzO8m`B2|fQA2HU6 zls92ieHK1E{GpoHURlssu2^2rPlR2Ot@y*vAnu#pV4{*VEnX zQe?Uecnb>Oy6$}A9;b^@=hS|5`@m$f!nu<>!R@G9D^xv~iXZbCuG)dg*kEFR3h!}k z-E3*%+=pkHyGJb$5A9uCV zt_p@->FTWn$QjL$HaPTc;YOQ(gkL$W)TiW1ov#Y0 zPLy{wj(4qKS(VufM>LRz-pHU&;%FO9C9nJf=U<@x+VIgI>?IN(kvylL@$XYmP=L%Y zzP4h+hl|;q3jrNJ35!X`bv-|>xf=>> zvymvxAzw}$(asJYyCTHotudrbKvcl$z}dOn36bd&ER39mDcYs_SatO|MlHsMHTW2~r{7 zBg#71(|6A#Tk~j7YV^9QO zJppv#lnG_JSD3xjT~;zH4Ze}K_09sv7hH&rYr6G!&;}6WQ|6q3)W`}@csxSr}IP=K8ukk{=a%L`n*P(WrDbgX+xXxz`W zxW|O1JV@c`raWY?En88mi}LvlV2)=gv+rpE@zGVD_r&M1MZq`Lpfu?eNkQ#tU}DXyyA&y0U;NZ9WsGb z&-jBM?CJ%(Uz|*HD~3xg&h&eFhuGRR0*j$^IsEyp{Ic(XZYnr_V6oM#WW_V2Y4zep z!*b0%rNg1U_xCA~v2!LGb{^+PKg|2m#41|)Hd&(Nv;^!Upc(;sRN0m!1Kue442tKy zTP;{r!5!D^+Gm1F3H^aPEe|P$9P#4JOUMbwxHry|8(E%62=ro5Sf!#P4U5u=nskT5 z0bTz9-hnWmM=Gc-cyl3%Rt%79{6_e zY|Y;K0P52iM9d!A@z!x_?3P`X6HDIizN%#=cUE7_pGq$HsnAwgybxDieD?5v=EJ`> zAFvk%e|YoZ&u@j~37Th`C+9^yDV=sUr`=})i7w6RJVp@ny)z{9#?&0QYrc&2l$Ib^ z1)Kij?KRv@@!3a00L+ly&91jj{~5%CC*~CU{i+k?5-<(1d+5{Lxv&rc56xTEUVdA0 zwP;>vj{wiv#6F#TPF`byRuDme?W|mLFDlF9}^sys#)^-{Q|dY@Nt+e@m6l(j^(-XX?1RlOcGtOt=kVkqNjH@>MIC zNXIw?dLM;sefAPa@EF{S|LEaEmk^@o>5~PBqIy{nB z(-OXa|L(LdrSss+r16x9pxVSm=~vbmeT6TJX(ezdCdYS!!;VRBKT7+`&9VLOymFSo zrD;CJ%Nu4+*nLgdGSJIJzb8Ju)EK3heex#%%-X@-|0;RqrSxAX&tFG5X~ZQ=EIyX@ z&CA~S>XiecTZ2rB6;1%(>tDLWO>(V93Ex|};2zzK*AvLs0f&a5%UDH|X_}Nv*;r?c z6p+;js+dxz!|!=EPC0P524UQl4<$GVUMSQ1&?hiA8Ud*SkI(3dEF%-?V}fZam^5Th zuBeX8r5WF&O+T9w$@Pj9j{}C68v@T?-7A!hIDT6XPOuK;Q?LMxpZ5m(B=kmOz8jAfF3)qfe zKfwUPDG@7QPzPpF9XTCC}ceQZ#c4$nk7USu5;SjR4bkI zPNoaXL@Q_e33W)hkQ4Sl!$2wG&LfEd0}iibfL#~qUQ1&)*TdvS{KJ7AyF<))mrhD zQ`B#^Bl_@-zwGpiLiU<0g6g5CgJfLVW^Y^Yn0LbsU^GefjG?t4`8J#jtGbQkL2>I1 z#BHhJLJcw{Mv@molbCxis9LJc=HYKI6XpeGm``MgHcWk{OJzSl?YZD<+{dGRcU$1Y zvnIUZY1&0H77rL@{`#xwBxJoYADy3ZJI(QXSTI~!2kUAm(rxejcuSs2P;PH9CcaXI z221cbjk{<}*Oh^!FxkKBLDFUml3zW!Obf3P9+JIr%m>{g5T|-@Upej_YW6kk%yCco zp}Kou{F5siQ@vMn}o%Fje`}a=+!OImd zFtR>gg7g7G$2ko?+zB5aGOi+qHHn^u&l7Ql37+%BpS7A$<%2|O*ma0FvDVqD624yi zu9cvEoANd9L|_o#ql^MJMunV;e8O7&AAW=Zh%{tmBiw(p?FR4H!p370E_{BD56zq2 zrOK&T^MO#612H~?NVyk7mt;|oE*ZZvK6cw>WdcQZC`l^w-YrKkXMgJ6mxxOB8KK*9 zVVbixU8BSE8mJi2G#!K=?OsDYchR#Ft_A*}oWn;z+FVR>EuAztxs&*+_+eU;3O?4< z^7DA*D19HZpMjL2Sf~~T|7~N!`5+gQHQCv6952I9K8@KZV^>(rkfyTnJDXhp{qRr@ zj`w>nmLx^gmYd%9xA@v+WH-GO42!gUxYbq>FOUt%2`kNscPGDEmb%Z_kNWh2UEJOC zD8_TFi3*}{-`Ib(>X>i6Ly!NC9OnE282f}W+m*1!kzU!*EMTaf6+CujZWtzWgSK7k z_z?6Du2mNB2Fb~JnPfNkt0d#UZ_Mx4Spm)bkVd2Qo0$akA(unEj47@T*u8sIAusu6 zNZg4ow2sX0mYL^nI#mTo3}SCo?V7~bi%Sm^K*Fv-3rr$?XD>lkowc>%e|FM_m4lJ# zqv)RNcR$Oqvl)L8)$F3iqiIy^K?f%|?cGEOKw0j!5%&*Y-*TLC&ei~h$kK*iA6iVK zJ1FWAY?xyR01LU~NaCw_icKvu81A{rb{ki_sT+r>=@vWm=@LPj6XS3Yhs39t>U;Um z%YYEt$Vlj@0wwYjka{4$s+Y(|q$V2H?L-cJV#F#1sc_G?!hAoHJw5PzPk{d1sQv>h zX7H>j4`sRkd5RmJEmXp)5R(1PCl$V`w5^RHas+M6S1!3rYB`iAo~+A)SWD})1@1Rw zenJ`PUy;WWpZrf3(8xDdK@jKKHBlzKz|QXKqcXvhvcpdt!QxPEXyRZP&aMb??BKqw z``G+s)@ch;);W0cb8PLHABTmx6R9iotT{=5`oig28+)){j%@~~Uw?9=0bbw8#ysyG zIc{;+YAD{EbXK&`a;>t?!zt^v2Xk8j+~VkmE=5{s8oev^zQTCjJMe0<0P*kBWc?m> z@?ZGqSA7v2ddZI!TC2R#8Gsi^ppM#ZPm@$rpYzBWxKnnev6ct$4N8&vxZsE~q-$EXGH{nj z=_gvX;zYN~D>Ef?=6ZADq+6`k?)E=J0qH>);%THrUFWk}7m|F3|^GN?%Y>6D# zVypg}nt5<@m#z~4o(O#qzQ!*V1`}x7E3g!!WxXZOHH+=h>i3D>w=ItA17+eCebPd< zK=pgdNuvjg^J#{Gv=pG?b?lOWBb+tt%EW-H~K?nH4X&sDNf3oXyRoC=F%n*9l_5 zykyK*DQv%T%zqagB2jsan4JG4n4fUv!J%vgCGC*E^_@I2W3j0BlCo}Ys&VurZNb@? z2$H;)?u*P?B=CKlZ*6%;3^%V*tN)ehpgZH{uhi7uNpXFUe%)xo7d!v&egS^-dq+2T za#?XnC`%O{j1it&=vcp35{Se6`d(aaZQ1JeypoyFs)8MkhHGOXWRW5f|^;WRUW(PL#RY!j#qMk;|FAg_WlPvAhdIHd1a##i^{F{eBSL(W{OzsQUNr{;R{h=`{uyV!iF9@-!to zyCdoJD1Be>yklg&1|!eELjZ8+T~Jpn*;NwVNp4yp`< z9IU`EvfP&=!&KK2Dsxu-xVcAz*b6HvOh**-CtcKt^);+U(0<-0`hb~gy-11Y?!>Be ztMa{aO5=YPi?$y@ES`4~$?((Mf8dyZUvL->#;c6~y00<}mo+o@zLEv46ANCvZ>aYO zK~i;NeFzH{g+(D)AYnB|aUZkKJ4llXxj1-N#UpRzKdR{c_ zZ+91cRx(2^Gj)8$qCE8AJ@4QNRsMN}yr4s^`y63%`2hSPGV%ONV(IDv zWUSQ}7xcCbsLUA6(&W>H4u`f7?$LP5M&rpz{k0Xw1Cj$}^)K{_DMcFhQr7=@TI!_1 zeXo;#arB>!CHalX|GDx1zWvLzGf87fxG|#~%*>4dkLrNUTHUpa4K4_`#ZSsshpMxEH52AAUYag{!EFxS(|74+ zJ6W<0KN6>d^Y+%4S4%dMN~4&gjC$Kl_)Bj6dIEnx!_5zGg$wsQY*iWppFiT6Q0D)5 z=s;KGam6I{*L`SSzt=l%x}@@bU(2T0eYq{U+v(mnQ4y zdV*oc86sdGK~^*dmS%r#Ex1s1X8D`)g}Z)FWRkP)^*V)kZ0wKApbw@9K}^!0%hVxc zi9*B6_~GaOEXljDbR5b5cF_5=9)In23EEd03^uIW6LoX7GpWDuWWVYfPk3Cge||u9 zYo6nf@eXd^a`x^1s5Bk8J(*}q;;k-YoLP520VsBb&o1D$S5;Iwj_&mEli@qp*15{$ z{RhvZzVhG=I8+UU=q0bAFHa7Aiuu1TlUJP7%zFvS65u8^3Mf)fOs;(y7#_ZpByo5N zXgF=fH4xf3jE?!Wc#1b%&?Yiyzaw-8z~KAhmi`TCsJ)DMO!yfT_a`dOd!uR%y!5DlCrLwNg0eLAnQbY>$`goe1gNqO~%MBffosUrXl%=6{HU$nis;nNIYTT zZ_7f3xYkq$>+xT9|KC*sPG$x#u=#zX1lr{Js7sxodC^6ivg<5xCNgCo!+B8;$LpPK zUtOC7)aI<^4VK2t6pS?U`#o8Rh+HR-zs)Mw^sGsadB` zDP5y$0Nv~SME|C@37aWT+~6-3@T=Mwy!FETu67*sKS#V!8R7EAhJ^zL;naCyVIdBC zS>N@+YErE*U+3X1{a1wq*bgNh<}Cp<$E0(}w*UIWUsPG+_5^g2gYqN9q&aY6UF&(K zVpgX_esQ}F0t34ZV$cEBXj`hhK1U^RnnHN&FvufXT`5eU2MWfiir5nZFg`I+&~ zj&*y|9X!{!#fj_-ti-o!T%+AEsIn#U#>jpgj_x*_VS~l z7W;kY4G6(*^)+kimD- z>Fa<=x1Dc&)k}b8Q;F^apU;$)qG4}CX!)Rt4+q3q#n^wy99CQduq8c8JR=4@hBl&L z_f83qF20M?9qTm8!d-V1XtKds;fU1nr!YV>Rq-f3otqZc+$UwujPe5R zut`SEI{-55a07)`v5xlB$B_qTKRu_XfT{I3`aE0!OmK4gp;JcDdV7 z@MNs|oAkpB+8cWDLF|pO-(oFV-d^iVZfrbVWS6j%_U?mRmY}e|{ak&|0F-on&Ayj{ z_1@V!+7_(_w%jaAZC%Dnk3%QSty*t?p&##)pfU$D3U(Cn&FPm9yI>1pp&e zHViDXcb0{+;LxIgD=WUDSy}&gK-{wY0`nhoGoo6bksQzQK3$-Ni169Jq#Xb48tH|g zqyC0o&)QG0i)}*dI!?q7K6Ufoo70@Ew0092j%CJ8V(Ct6icvDBN$uaHYWoMe1D9T2 zD#b;CGwRVNHUcN^%f7#N5gAM`*g$yqCrAgbZ$i}XgV3IF?&T&txH<|o(xhrhHtq6w zP;NOU`X$Yv!u6L4#kHzx(uA7Bh$_tz=}a@rhNG8*4a)hIsdBr?c=zj64RntkwAHT9 zr;xWIW&Y%3=XN zJ6STmWuw93HW#1+lvX}w9UdOmwdGxUrN5DYQ(&96YiVg&GNPqn`g2V0eZ$sqZ8K9D zct-`k+=b#A-q-t|8Vwk-3kqHrHEgG$N`6f3BlFl*b7M`PWRWWA2_mf2=MFzxf2zp5 zz2EM3T0z&r5o$=Tcki2w_Ud@(`x`~Ut(%xv$%9pH@NG7Gh;3dRC12E(^h1i)r3s*f zItikbuK`-&07AyImOY5CW+0Vp?CtCTXwN9DT0(C=Qrku{i>Gt}+~Hm?KUHIE*zG@j zQq%|K%B$<;9Sw?V_SX^Z~`S>6eW5?aAA`6)wYY8*BSc2%$CB~d>m9PSN?+`bE& z$B`8NRdIN^Tv2g8sNu>yHqv)_J~43<>rJ&q;8+t zS?!PYhM)YM+eh^c=c_?nhR+#EKbKckA%QQku0|b7mml{&<3-VwvME3Rqyv~Ms@6>C zHM!_%3{rS!gr;27JEOP+JFisBez*}aRJp=LoK>ve$j70frB8~OiR4T~oWJ!#DENoC z;AQE(9PNRn%saJP2h9_Aa12ObAcTN`G;>5Mgl7Dm6d)BD=v5>h`{WnzfQhBpJXCQ( zCkhS1vfrP#*UB&Twtj(^bMlL$$LOy5{s$VD4R&Uj2eDD5^3NaBEu~o~9?)zgxo!mL z>}j=H%&*^Nm-gyV_D#b74(tbEbsYzBDMYrGZ^gRd=2jLG*ADq5PxmLnHZ&v1+r0pW@*iM_hIp` zY#|SBqzdO-$T2O=UuWdI_j5T%h0#CC&_Q^~x1L?#B6v&1`jBA1@qkLVsIhcv%GuEN z;awABMsd-*iW9M9{SJP$U)rvotlZf(N|rCp_B@JYRoT{519@Gjy6Kl{Cv#=d`VERE zj2H%Vrtt&)O|3Vb!&ipgvxXt@mBYH)$FH55U4^u3t59V>&-dqW;c9F@5P4Ng7)fPu zjCjaLg=t$eu?S;Bdoij|IC-`*UC{iU4t88BN60id=yU1b==1`Wr6Cv$yPVpyO)0=KQKa{wCV#K}=(R!WPbZemJl9q!AX_(ut;tnIVob^Qh)ifh7>vsu<;N=K1U3 zUuW=XoBR8u{a!XlZoF)Cs!SWyxEe6xatmKMy4U|*-r7vqIXBSD9vXP5l6Pb1>k`Vm4NEs*N_aGT95#fd*hd?m5kmz{Wn81N*U)tQS(S~ zTxw-TSO7!NIY1Qq*`mB=U^<^&Hedgc%{{pJ<3X`RM%ERO{Y8zD@i!ytoe<&8UUMTt zyV8#ger>DRO%PvXTs3C}xG{B!Tx zyx06Vdc3e2r!`eC(i$49z1tVxP0rB=?HM4L?QH6le?DE{UaLqxThDgr6~-D%a%IJ< z-A4k5U<`0cEJ2`UxxJ%3S+WV)gpEpg%7ILu=Uu3b9Z8h*n8)#e#9W@z{)A~!^PpMF z+e!1SxwG|}M@_{^8%a>Ecu<=9>dB145&V^N)^~~V2`2d|>p(|r)&rS51eq~*P?_|K^1)2qt!qmU?D6kayFK6Bc-MZHonsC|YB}@u`VI1wO zn^r{v&>qe(NEbcu>O_Sgick=>l2#;=H$OYuEK0hF!mgLIt@uaH4^QL#OE1`z^4~sX zzJaTAhq8a%XN6;`5*?9L3384ATa~ENel40B#G#mvqh=0Rt8Cz51u8qZc^HY^`bZ+= zO{9T)^49R<@g06ZyF~cx1`_#?gBGd6{AWEO^yfRhGJHAtkzDyCpo6qKV~rfy_pEY8A=lbGvhUI z+T4$MBmF0)2mR#F@ysD&|AF3sbND;vI08x)`rJfFAgF5-*_!5exB|mI$XF< zSL|0hs5Nbfxth+$_w{DiWs_^*y>7KV&Q;vg*wazp9!Nfa=r`?g!o8kVbkQ*Buy#>w zc{af6@bjRNur1m7m~njndu57ayGw1ipUy2z>4pXlRV{lA*n*TEI#|A<$P*=A_Xu{D z&3n;zj+)*G$W3-$Vg#~*j(q)3)0mDdnsTp9K z8{4&tSzvnqD;@r)*em}WuurwGqrdBQ>b&a&v8fmt(P&sFIH(yoo|%E*Lx&kJtT8~E zn9KXbW$waTnA6wSXN(edvLAZTtM){SRwPM@Yvs*@1HOH07RCV>;}1dbl=m3 z$#*pKSE-XL@w6xAK9Md;Jn89avaRGl?`fK}>xfMDG^{w=Z1nsX?Vto#x43i8>SpzN zlu&5-KXx-K*ui}%*(--RE&u!hdyJ)?WXpQac|EF=*u?GGFyt0}0=Ya3(p8IhX_W9S zxupc%DD?qow-Y=E?2{LAC2O zBX`wG7lg(=zX&ThUR<5);)Bwah(MU}jD3^dt!iii8<5wpT}A`jfcqQ-BkLr-Zd?=h z;06mMP$s4$i1r`905<;7Xf}QZ7%Nt8Bf^Y}W2o9?r1-@f?1$I9fafGHcx~M07Q^ zi-L*oHOY{mOTWYhX2iZYOBEI#!`WHKd?w>z zXJTqf)=RZ9CHUR3!fh2Q!@ymkQ|#pX=)TugfzzMlsUAh3!ocju&%f(f%-WQ(PZyGffSb~rp zO(40DYf@F1aOon-!)OsxS_+srxgR2Oj2zsCh)~0%=Tk}76tjL}!3ws6S456YYE^bA zkhjlGNf*97Dl}1LE5d$=>jen>9m<)wq5*>jnxdW7H)uz1bG>Ktg9sjdfv=zL^dxuc zl6_(cmZEasl~b#>nq^yY2jG4C8qu*S&=^)apj6wM_0qbg=@zr7cmABZTRww6EeB|u zOcV+=&t?gPpk?J3z4S%(+kuld-K+>S1r*TYt#E*%yFX0G_M7 zT|g&k`i$`~{ux*O(T9e;rS9REOc-|*TBebzALV4GkT>lz!qPP9o*jRy^cX)JW>(CN zYU}WbbNM$E}u=-if;DNMrd}?xUOHDJruqe;nFOUHdnrUtlZr-@sIz$wp z&JIXiN+(rhYoU0Kt2l4vXnSB(FRc2T4BN_aPg{(z%bqIM|1k4e3=$+bQH9(b6-QgN zpR5}S232Xn?pPHqWwR*e(Xbpz#jc7F&jr{PEzz(VhXb?~`5jnAY`)3lCw;OG9%{c7 zL1#w#0=o~bof0IGQe$S>Lkd>t&Z7<}4KVZl<}?fHxFAP<5$v8v-S3(A(mS+`b=EXl z<7?$f?Ig4usch_Nx6^tcKz(*jc%R-&itvHQ%1&Y3g})k_(d! z9qW_#eta7WiHu=3I1)zQu8(dA>R{K_La3gT_J`if^+5V@D1o`M6;%zT9VlVS(k~;y zIRhP+)U?YgGGaHkEs7RP%%$wFR%+|>+Wq{%0LmNL#&wkI@8(mZv=a_U`GDT!)er9mTtG9it(Pyn! zw|ak}#o=Flb=jBKCzT9Wo#Cv)@aqJ1MPv5Q`A z+qT$5S=95hk#`%2kRnw$yh?$IXnb>RPv^oopdU2nTcfuS%QB<>_dlWlBod06vi#x& z>YF>`r~71mo%xxWM&`3TANId}G2!i4tC>B-&?|EEksB)+9k>Rkj1oA(4Zu9F~ zo%hSEqJE`oM?4j32fefm?PW(ug=@mSo*%YbBgS_GYDM#8fb_r{TwK153 z9bOP}Q$c^UIyJLKU$?$uRmnM2oi;*u7q)|QukDKBg*II{TK)&(BK4q85&#J$y7ebm zi$s0h@e+g zG=Aiyhn9j!Z6xq^kqw^&qX~ym9eED&agM{oP9r0_=qlZ#poLJe$&Jm*K73NJe&tHDxc8nQADWS;HvfYiNXCF3 zgBZU)zdk|&s}{Nhr~VTD*yiZc+;lDv9!h8s=r8z7G?9^t5vhs6S62(n=~v`=tU;=z z!v#-XLD?|;Y*%o82Ef5#diUGIGAR)x#~g^pi?g3(c{ej{tX7&@5Rac|fmvK%j^CEk zu!^BrW4>8itj_v`-GJ=vKKA8n&teBF1?eR5j0jI|n9EpKussn3U@!+h|+u141d&Hc@F3nHB@r(y|XOYuNI_r}c-mX5-Rz$mJx~?I1-2XH z@nje={>RJJZ_eW{yReOlQF!bjRGDL3fu35lAYCuC;h+JFEN{>3aIbs#N%rj%-%aOK zEd%*F$Eb0;#bhePF3*;YeHR{&^2$4`B#HKZ?vd6{7(2r3@^75-UY*~!A~zK9nt#&a z2;i50cKeT@eIwa@C|C3;_fO#l`+@ z0vqft5sMszIJ&)=r0NyRsG0ui#>25&-t`ED1)#Z#Wx4_-udZXg4mqQ8n(oIVOJ4Tdy6ng5Bmez>(~)7M&2KKHU+!8C3iZ1QjZ1Lb{$i~_ zfv1sU2~aufz4zdW;U;aoH_70C_=@OOo ziWl>f3R5Xkwsv|cnD!FS;~e70Q1R!4J^al|Ze8Vuu4$KJcp~2kV;#R2AYtkwt`NVQ ze=6$HYQ5%56xbQm2+jhNU~#S3G{IRbzLks!UG?K9AkKBZX0qXlNAEw()K(QQYTb{kI!%rWfje^ZmOMgVwTT~x|yY<6XXk}O<5E-KJ@ z{_;bJH{dhAp_6tJ`YJj%#G>NhG$JPldB<-xjJ?(S2!OA% z^@Aq1qR8)|kHwR64MY;hD;v$(o9e&cc)ak!b@s@xpw3mTJ~`tj64`6{ytm{N)k?N% zM?emwVf@MtfVVP$jOz_Z&8hlk%sQrtON>ktJ3&5M8&T$%(5mu-wXVe1P=tWKO`BUo zzt?bWq_6}vUNx5LUx{U#%YO@hCPqV4|F@WIv3XgvbemjxpN0G1i;g;@11fIc5<$^z~ z?ch7B_>?e<99g&ubh5mnqCLvpIRhx)rd`$wZtD+< zxp_7-@DEBfY*;K`<_6C|qDzit&O@~-3zU`^L#7mkw5|jBeO!32DSX`tVjIyX>$fY4 zbL1CD>z1}k^63KhK?RJ#>m6(k4o$dLDWv_@enismxgwvliHkwoGtZlSRlw{A%k)6f z{kyWm0gvMH!28kRVR}zJ0xQSv>Lom4{rnpwR6QK?-uX};nLDgBY`imY`ogPgz(j$qR*hb%<6 z`1}HDbEm8UJ)-SP1MfqYA#UOm$1T ztD5Fbb>7r`l3iCKSPuDXRj~bW=bp#<^Pu&ZGDMey8DOV5MG)HexNOzbjkkhK?*%_I zQNquKYcPR@ZJ5Eb zuvi^m%6`22pCh>2$y1XN#7zACuelK7vn*a-z3q+t$eD@r#zP1$Y0^S7UJ6< zD7s6l&LN=VOA-9VWM}APtpo0U`gBNM%K~ZOOMbc>GzCCeRO;($4@#yUr&h3Pt=zwR zaEuB(N~(>@=D@CYtv=tj;$NCQzh_v(0)&UvvUl0*H|raYSD9xgN?SisRe9ggywj># z3TWzkP8Y+bL-9P05VKOF1lUlprYlMTkUoE`zoQK;uiSS~^XN>iTpG(p6;yF4*QkT} z;wRdXzM6^M<=FT)9Brl*Xh<};hr8(r|AdO$^IN0y$whfxqkBBR)kV`ya^xBA+QteO zfF~z+pDm?Y+6?q_6ZUP0v(5hy^aRlX1w5zksJsIMti4jWlTALEPtKaVvE)`*z;Z<4L6Wi`zY94 zxg?wGF@g!Yjy4EDn9zfoKdNL7$K^vbpXX_Zr`gIQVIRE-TYxwL=`tZL4xS(buD2N_ zti7|A9laT|rsF@AL-c1p3vn40hbUfk0q?|D1i~b7@nz|T&xy9*AIoXk8M-pe+Dp|Z z1v*V20snc%4saj*u)2y!7YB&Tc~?SOuB|B77z}+<0K%bP5`&KbdSqD&x=icVH=XZy z)zU6oHouEgq|#9g(&4?Y9VvPQ(|41Dn>R2faM5haMD-q&^P5AKwvoB$uvUf`7bD0D zl#oybq91y%-1nS}kwRTk;uz^c$vAB^=WojG{+tR{$PiRJ2GVcIOp@g#;p%uC&La-^hP(6MIXXxyi(q_u$!6x} z6~H3j;^cV55(pD&zHFQ>2_n-4Paw=u(zAzKxN8Nwe%7jm8}a4*c!Qf%KW*vL!zTG7 zQR|q0^DMzY%jgM^{2RYxi}`?l2#QTHViOSIKR`G}8GW)F=k2A+Ti(Ic$;X4)s9<=a zF<@Ssq*X*xRCfUPIXPC;n;D#S5#>f>jwWsrR7>F3UCnf^5~y0 z`LyVx4GQ=^1QD_gNm0nw#|p@by&<~t@l%UQKK8?#mler$DoDWijc)XOSwheR5NDDy zN4B(CY|$?tDf9$m}Dl&S36G zQbgH0isgNcvNF6-^Ia35@u0T5*~5O!0$KAkY$=O!TaQnaA5D8g$sTbuYwwZaJ@1V< zmin=wsD`;!fyu}y$i}=E5vT+C1oxs zkx4%jw2fuTE%v~nugCp|z>WFi&4>G)-tWmQINjRV3B1JbZ-P9&QQ#|Y24tL-Aj9dx zT=1~v>i!Je!$|OC#dEY(EC^Mhq*co8v8U<=O%9e|noV^ZHP0#^OLzc)1VW`ND~})t zkwnZU~a+-vh zY0~;caC8z_f+nf$*bOeNWGCafE0k<(lt#IVc<$|~1e^7;<26kmG#-q#U^VpsY6SJT zZBaw38$1RuEJW1mdpvX|*h&uS4dJfmHHNJoDkVutz5BfuifcG+HNtAF6@P{*+O^m@ zngmb^w0I~q;w5^tF4T5Qxyi#l)~%YYku(4cv+3d_x$MFB!&k8|-u@fByH;w&6lJp#3f@|?@qLQEH-;UdNyU@q8k77w+n+iP7gOrg1d_`D z4J+d&zU!gBB6d>W3FHL(`bNdbUGgs&H)p)4+Rc#VIN7oyE=Cnql?lAzbvX@OdaYEE(qG)Gx;_(%8}(@%(eihatec8}EsP z1z@aT1M5>-ZssT8^*Sgg2{Y#3fsObiy(`$X|KV zDF;M+GS;$z`|&+yCc@SEz-$Q!*`+KG9&kHW#hu6TRt@xW%I4RWDGVXqvztgcc^m1= zh!PVMe=<>4>TEobvEURtD_m9~h5=`V`O%ZEZuWRrd%TvE)p+}F3f=%J%8I>&34xlF z&2`>ZqR^VP`O48DV_z{}7#5{B!A}_!_GFd8o8%OsF>_D^M(b(7PUevCH1rzNg!H*g8buz`xRE@8{Ut$-}~9(v#uB~7PZ1eaZVyrg6GIgjW9DUZXb#%aU&pixc$X9ywk zuVF{sIQX&U@o?gm&joZkT+3psgFW9Y=v-wwZ{~wwa(DhQZJfG{p~bPxRWH5J$HQR8 zD9O89Oaz9l>{XTfHPP(1!LV=2^ko0boO`sgE4HEfU8sJ$Ya_|1VY=98ljSvtx$q}v ze$q?Pu1tOUiwqy7+={l8WHUic_zz3pD*)J}xV>kR`-QQA(f`aNH5m^I#|djdGYLg4 zuLk(>K{t1IW&KoQDQpgm+}?LD&iTlJ{Ydz!&fG2fJ0xVlY2@(#BkL`oqFUegZ$Tsk z1VnHML0Tz??of~r1VI`EMx>>?8$^asIwYi|L0UQ-It4)*hL-N;eFl%`d*0uFtywM( zXD!{c_p_h4@9X+pc4~N*IV#1q3}nX2 zW9-I!TEa)t0voEXEe^&-sznNu%&?kloiLW*nWZ%MD8ea<*4K!4uLm2d^p4J!#H>aotl{NWzab)-VRwPKcWh*K^KkOS$bI|;Z?*F^HC`XML|I()CfHt>iGV9Ey>Me{@F-F zDn^G1qm!U>f4x9<-CD(@cXrzl+Pj5~I~zXBa{f z!luStE+vtXYCDV{ihIdnLFZ9jQ|+d|9z$^0Ga;mXG!xTYXV2k38}t4KOLXo>0$6pw z*T!%yP4z`~gm=(4bkCMA4Cw@;w@#ncX5(Mzj5;k>qMt`~b#oEi);S~`ue$t_f@{$c zBp@*+EeB^M}getCHq4JiE%6JevtBX)x(&Zh*pKP2-M-mBFj-ylhy+s6gNRH_8#gFtn-vLN%7vd(*hN=M-Tr=NkZGp!u z?0d*v?Y4>PgBI$EyNNGw+NK|%5wiLcw}8nWc>Y8GmB_^1LD#Ip>E~@3nu(=_Ct5qBDqgB2jZT`q!<{!saWa;OyL&|R~23ioIUkF|xR*c`52eC!K4 zXEHYR^rsdAZ&Ozgx28;sN3xs2LA;Qw+bDJEs1zbSfPmeCmDI#dw5(3Qn})QdgpL|S zwzrk6Z_t!qfGt{n^=6z05Bk>3yAWiH$!W(9_slx@_Q* z$Ot-t#lX=H@`UqP7Qb2-MBpy<)bFPB`u(suGJh{vnq`tn{t$KSe=egBppzxT78dIO zI~B&VtHNA2J4YK52$}G=Lxw65@GSAKmT?0yBWJq znGp{$-v$+vO+K0^WVcwbFG%c+D9=B5&X$ldRB3XO4V0JMJICch!zD?w_s=)Hvkx1_;6C+oTVS&}~J)WR%nMygn=GoZ1n)m%ly%{{>`T9A5U?8)f!te=A z5_q&8&b`8tGfPxaE+Mbe^sDRLl$?}#v#Q)`jU5k1y;-}O9ZAoqCRzQ71FMJ^X%sGB zK5v|q@N#ySQO7%#jw!K#QFl^cTHA;*lfp}aBN(X>*={_actFxNZM6>RSl=jjS6g+O z&O~pJ<6_GM4c_a7_CUwej54hNaP9Dq;&Jw!hHI4qEdCy4D$EC$?<#@7`Ruk$KP2u8 zhc|~6i&zA~DcPwuyH3O6*Y0M?%?C~z48%SqMA+%(Z^@$mI1*EBu!{vT2*N%*%e>7< z$2#G!{%AG+4$J&5Y>+*KZ(g$p9~8LDN}mlS<7~V{;Lg?CCBcpRzK}brgpy}<_N}T` zPS}Q=gSDZu4xD@fa1SezZNHBy_WL*jT#}5*lyk!Hp34kogW;y05jY989JCUL2cE|3 z8mN+oJ(a0yDS6glqi6*W^7{De8WE5Hl!lj}4}l()ffG>1o&M^hDzQ~$fLGg^crnOW zMGaY2*KLyH{%Cr`3l}SgxnrOtJB{N9Wl!k2#zC#jmV^C6725cZFNK4Ac5#3Me(!E!c)-k^Rni4Np#6T#D3p`D=!GV&schcD{Icfur9!9SR$6 zQ8{Up$ZPRc(d&fE5y8|~R#<5Hdt(FCEN>qY9pL+iSRXQnlvHT0S63Zn#O^%BR`HidAr zmbstWmrWbzQ-^CcmpiZA0Ais~Yqb6|ItY>YBmft$q z>yPGe3N}!DiURFQsh0X8_XQS5ltaTJs7Z3<=`pJG2a3CS#ABEwKfhpPRAS5HqlFn` zkF>}#&LxDqCDSK8s@kkx&28Y^@HNbyc0V4s7wo7uZ<$1JOm^zRiY(TA0M4Y zxEXC&Cg0!_ZnPuttb`bqE+eVPpSt<}Q}Yat0lPzaF&|dS5Pm1pEAv1}Z?#2*zNcG6 zSS~AeVJqo7AIRD&B#!zZ^TE1}n1Po;gTbYNSkgth4>u%U9GTfpu4o9#dskIla&+N{ z)#YVu;#0qSaGl09SDF%qSG2A z!Kg`~0=XnCYt}1@MXGluH$C|j-W2Iweq66Rd@ZyPMKHd3F(q)23`%tOUQPZSo-_~< zS*R*1*2}<|XZ>L~7$;cAZWB`t#Kuq~fmwf5gmF)T@mk8|@%Vw_<=*oeWZ0E^8{vJ? z0OES^X3;Q^$mGo_15{>CiK{Yaz6|>Uk1sULcJ^_rXvp1h>C4@=_3J@YmUfF}WT)+q zytZ)xJZ-XJw9&8Q^}=Ta-s;>rJj z87P!tbLf1}e;W^$a@5MSHa>k(anE5$Noo{jZUcw1zz;Zq+$hfbE87l+KY033U||T=aJvtH|xfFKmU{lgGaMG@8lLUpYo} zdKV$QX0_(D=0z&HF?`P9y#ENDSn7Ua@kf=2D=&5e;r&cwRQ_Ho=7$FC420wP;d#=SEy6fmtb`mFY#ciuQkQUvI%Ik5fLiQX)F;uWwg*<1$sQNs zy_LgxUTtAwv-CitidJDDT?se}B(Kz#W@B@!p|UzaIHA`b&@tEjwYVrw6iGWXb@=-` zYX~bi)*7N_D%|tS#Dfpvo)Z_lIoZG3ME|wzQ}dIC37$Z-%S<-6iql4PwZNNlv1wJt zlzdcOR}GWkuAQU7I9J7KJ*7_&cT%jTX-iq* zdf)@xbz*^~J6)hKNYYD?w+>2y6@WVJ#jEB|vxdq+5Zb6}=@tB)9~UzW10$f1Jn!2~ zo4&uTMo*BfOe-&f8C2CPJ^>-rz>6qnJUH=gCYgNdwkabiencFP)dF<+}kG+RTD~ga(LNy0v{)W;=<#o^8NJ-l(D!49I z3ni8Enr9L_mKCF``g%g;&_9K8A=WeEE3^z>H|R_gUX4J>%o-(c>o4333x$k<25PVK z%tmOf>ITYl}{tT8AbC{8qs|e7j-!<2cRrQ1qTJ#YNAgA4Y+7o`QqW5g4yv zG7S|M7kuBSa@+clKepqzPJ>kgR0vSy(uzA43VB!Sxb4+CUXoJMP%_PdwYHHJjt$(2 zZ#i$O{sXP$^1DXBa$U^i08%PCQ;Lzy*Dc5Pi~PV(SjeG&|E^@t6$qFZMUq!i=b(bx3R1nhi#Zfhm6>-DEp72_M5B{yo;VY`c)y!v>o zdY*9w!W$T;?b4!_kV{JE{wBxGx=XXmlSh}Y8!q+(N3BesW?Gxz5-_;7WzXE1w=D`w z(OH~LlO;uH(8x^b!xjfjaxx9WO7yz*ifdFCM10!B86)e$znnFSQU)E2TjkK8FawAq zq2FA_<7ilvZ!Rx33C2bm91U7R#mv7dY6Tbq$YUVd&BB_)qO3@3{i-IG4d_why9EF= ztN_DLkkWYLx$I{-!Cvzy;_IvR8+C`e+TZMR?g9PSwu4TTbTxg8IA%Ka*}Pt{KHAg+ zuxM#JM`-g5X#z(xH>CMRw&*<<>{1$0pc8&JL~(A4wf}Mx6^EYU$Bhcr!~1|;yVZ<~ zFF}JBI64K^0*fj^8NcF>iWX!beLS+|TTAE!ylf_kE{T^O8q?qtwHSIhjQ-0^!)nxe@Ti^Q~2Z5AG%5k^Vm_Wm& zfOh$+1n7g&S#%6ux2UwfSF7K&f!N|h^7)Pum+=E1mtDb@ z@}4ZR+)qQOgS!tinp5~vH$U~2iIp{og$OIuCz$%W$EkXZ>YVx#pw`F@7C^K+$7cjUHhpX!6J)85k3*XO>-b&$g)W&vS-J3U}H zUU}o!l*N(L+A?p9o3S!k6V!m&A7{UNF{-|pCMZ4TOfYrQAdgQ1}mRNwe6 zK-JOumqH+qtVkFG5C%LMgCqDs3Xk5U<4(lJ_q%%XiGJT8x3*nhI#mK;=;VV~_l~Oe z$@C_?ytWKFQc&-sZkW!AM(DB_YyjlgHJD3#3m2RNV_Pjd(&}S;<8L6 zN+`iTU-=*GeU%XM%t^P@CIFkmZFEJ zMMz^e(|vqnax}QJMuGkIoX6Vbnb_qclpHvpWdh5hZPdsu)`Gw{?YVkw;d)83bxQMo zo21U~=&opMHqBdy!qL_qnso}df)=gW5;W5y_&lHL%q7%Dgupf|H!M$3waPH@qWv)T zw5x_tBR7%tp|fQlCxM;9)d6;mV@7v!3AI>DqHB8n+Ck0H0O|4!y(1@U0inZ!@dSu|yTWjU*_kl6aLoh!C0pYVj=<`H5z!nULjH^AL~mqrw4 z#jaWh!er@=>K&luJ!L89doX0$b{Mo`P9hvy=&Y~jmPB_hPi#p!DN;e4&VkU?NdUS| zgdWW^4!9fyA3?|>Xr!;D!Z^Z`9y7J-95j%qX zBYMQ%0NWnfR@8e00R+k{ojdaB_=Oc|p+mnU*m**!&}Vn7gnvc-m9S>Tc$)!0Ik4+# zwp5Da|Ea@60=*kpde0|eo6js_UIXZBzIE=OG!XK#&jLxe^VA__NMkAwysOE%JF0lGKV4-#lK~LgJUY-!VVZ%A! zJZjtc`Cij~e|5##TR+zh4jc`lWAh5XbwU@bK_=!JFhH+*;j48@2vQ+lQ+{kVdj*$m zKLsbx))}A&X@gcYMKECQd7xk#2s0j!#B|#)iRvaO5MoTH^hjx+sL-myI4PUfoqZ{+ zITM2YO+d0ZcZk45QrO?$0!VRQyZ|WVwOg4l4MW~s#05w&eYY-&RY9a15HLXSt=I$f zN2NqKgr5YBjkq`AkiDn2NQ0;OfAa*fOk_nJxfX4Jp7G1-+V@qFoKJMa5|_Q8!luGP zf}a`LjB5F&#x#a|?$H?x4;qBOGRijV{ znD@@L%J^3-A1Wk(wc~}ctBl@*`OjgRi$ry9!=V%>2~hMc2PcDJ;<&pZHzb_Dh&PnA z29bT|$9zV^9ymf?<1b3rgTs_eN!4f-hA9l1(D_eSN}f$C(ixvf=DIn!8)}kz1@shU z(*+GJ_V+47vddJJ?-9K0OCzNEas#LBL73|HD9Kq3n})tLrHcxsSN_nC$$JRuwr|$m zsPS>KM_dKAvY%5_ot;&G0yqP?dStK>QwwDzteU|+a zG13!JksnYz+vyxSOo@m1?16kB<7k@V;uJnc)UN94)$h#xvppskYN=Eq`r~ z)&sOGhbnmK$+p$6HRB$z-`N?~^CR7b(F#!O)ktdW4?huL0X?ACLW#H2bn%|qYLYS* z6NN{PYN|O*PVU7E1HEIFo7k>SOn_%!07nD?`$aC4@$>vHMbJ&2IWFW=WUe9c@noRrlF(!t+JNkJkgp<8_%%YU0~N)b{+Nb+ zMONAqLxKeU9GfW_IuFvkK7yDJ4t5vt#0z*|arV=|`3GNMKB4NA`8aqxXbABV>xAwo zm=1rT#Ej5zXjMjdMMiP*N**BkrP#NJ!0V`G^dKt8e_29%d*r8t$6MmC7kBsR%8$)k z%pCx2#d0fy1aQr(V9K#RMDURu=qJdyX;-1m^s z-!Jj{ZA=+3d30Xhk#lMJlC8n&f12(~GRK28;$4kXy@(WKr0&db*z9O_$gXMo{lbaw zpFkGW-uCZ@+^=yBx@?N~a}aDDuYPI7;Isc*@BO+~)d(#B+O>60gr*PEra-4Zl z!-bZ+%z)V9iP{p*)8~a>U#fgN-IAXm*%al)+(63p9i@+xdF?Lsa3QFRCT@P$B=?H8 z4WOT`GWt1wcv1;TEz*4K9c=`x4_5fjbwBb=G@jEzbzU>jOeD-K8#*MOsM@}6<#r#q zn}5;LDN;U6+`B4ez|##2pczxwjyby$%&}lV7iqkt-GWp%LtG2^Fs$!=cr?$N($&nv zI@h#sy$%(4joMP8KH}798%iIZ#qpVvDhajhOUEUqPM-$)P+m^&f4?)=Bq#Rwy%n?X&5ST*xW2=m0@9yzt`QqSo}2CT#O08`8@;i1a2Tk zZ*g+D4Iyg(y@Noa5pA6GTTbZAN<_3!Y&54$v6$+hZDUJPe=LWNxDO>JfA1c+WE`Kg z#10;`C+}Ii=6ED)AI*{b%3;&~O?d@IB2f0|OU!VAK$B1`O(92n&`Pfa`~IWr^owlo z{t5lzW(RUFd8g?d&wu9UI0g*oFBSv&&E1oEw;7A$yB$%MCC32o8VZA)$|6FiaD)82 z22|+5Yax+z=#h`TX%H{c-!A3oY!L$5X7i{#2hEEsPz&@9S^yB1cbkDtW7$}}wNF1q z#y40@z;Dbx?i-2D?f-Cab)*1{V*DHGP{*O?6Gl$_BH~@+ z9pV=bv``-mdp-dlsA|;J00Osw$7f4es7ISCKGZ*Z;(4fKXo@qsB^7QcGH*4+@l8U~ zJLn$IFN|iJFy>rjkrkaFB}wueyD z(AMW3&+qwYYQKaimso7TS;9T*a|vEJhCObkr-cq+G#CFC%5t$c?1CvP`L_bdyyF|F5)|)tgO+g5lB~PTBu1Jo&3Fe1JX+tE7?m&hnSxfm$O#PgCaQKjV(j zM-*L%NobBh?oIJX+fysA)~dg?03ewG{Ke&!91X?l+o3MZ(e(z=F-!3qmP+Te{mvK} z+i*JYeaS``lx6-t*nd~06mP9RU+V9lrNQ2(jl&g~mOWW9xoqI;hRUXn3=**V^<@pl zWOKO4nxihr1P>(yhI@XD`RAUXZVMj9kksF+{a11XR?{>LXGvWiB+P;8O(63awwbIn znA>G(?@J`hqUXIv-2wds6s#hlG4Br)*e94a)%M?&^S?j*gU^rkPHfQj*_yAloK1Gh zR{9&`{%7ihM}kp@z)|=`p5#6Bud?BPA}DZ0e}ZhTt}zY|o%JUd*+Q=Te=gl;ns)`{@4p`Jc5N zb#*H=s5>S?lBag{EqnqQy_LiN%iyqbEz%HWjWRyXEY0g|Y; zzd!Qiun6nOWLs9CXp2$`eyR`0hyrh0ssI>!*#ak;1t>nwzaO78><9mS7xnMr*gHBN z#Lnn?Ku4+X|9O?YvGFAIx97eC6YmsY>Wbm#xE3hqsATdT`T1WGiqc&Ak?#EJ^Q`bv zy?=({QNj8-P3B~=-IvpX)>g7Pj5yuE8FdYubK?EAFiC?;dT!j+(bqffRDTN)4_8gu zaeq4FWS1<9u`*NrEG5fNUKhuXm*t zy@sbVZrMO_)FPQMq;_xGc2QhYtAbXSn}Xfp4( zKav|ePy$rci`Icw7WM<$s9ED!P%<|K%nla7AzO+%uB!!nLnZ9CIwsj5$OahTCttei zw0J>ANG(9)U%$nFpInMaq1KJZqJS#HsVFde=N*&qw$$UQ(&zkt5sQm7U^ZM_F)vra z$V&0%j=POMF_Zb;@kHcC07diEa>{47Mvd5dBPKM&h_}t1Kr&cKd6SjQ=>6wj&Z7X2 z3=g_y@UCPig%AFydCqamy!PqslLUHnI8SJUtnZ)c47~SDK8%*CwcPjwi`}`0Q>imr z=<1+C)E|cd{VB1_rp=3#kLlOa&Bth41|xVOjcXu84HfC|H2p4I3+mgXv5=FU{9YAC=$D2&j_RVaX;-iYilH)z zL5lz}Yz-Yvn}872ld@{)15|4&k%DFvz>Ihfe(5?9g?u9nyVVXruKM}DKc=QEfiXC@ zq=#APq1ZQumL!ngE-CR)ZBDb!)q%Tsg@sp;KzPfWO|O2UUGAFUpwXUjIqm9m#8Xse z7YI_H#0EN*Q}}`MW($GXTL>1aQS1m(yD5&_8$eK)(9w(^{`It`J@4yzG#`>LGA`(^ zBAXana_6(QAUS{XEq$`?Ly`Ed37_u{$$)tRhGWeUvXzG+YgKDQ5q2Fq8xS(H8EcJf zyWRn`7@wus^KK9FCDN;*_19dy)G6g4%dJxtuY)BB%0M(SxOVwVyu~mA_;FKKC3#^V znOP9Z*SKa`G5HD8}A3W^}iJ1!2zipdf@(E<1$4&p#M02Rs* zIayA($xHy))9)t+Z;n8Rv-C3&E+#Kz%l|%dSQAoNyo&OsoP^qHe8QB7H|#>C3w{XN z!_Ff{ao3^nH|-%XJWSqJ8ps%7C394z_3RS~V8N<2x#s^E&lTiBVXsT`>COg-Le5_B ztvq-%{Cu3fW{uPLb&biiOx|?H*LM3c(`+(Vn1=n3lJs{+BHc$VD?R{7c~?SjhvBYR zpg1UR+Uq>V#)KLsTF(JS+cHK5AdNRJgS;H$z5FOtJLNr&j?<(=;2#&Ab;~{@Sv*=k zNW2Ri)m9YVjywPHsq&Z8#c?7)+&lSGe9~T{zL;e^9UHk2Ev}_$Z(rcS-L z^=~V$Qw=6;xr-$9VH;$XmohVs{*GTU3ligi?{M_fbnWoP@rIDEJJ-o2lfn9?6&`X8 zbG>Euh-V05@RnvvQfh80e_NH8+zPpV*@U1*-tuANocfwApvRApzo^ddltx;qpSTut zKom+&{_HT~7BH%Qiu1?P*4VPgcet2R9L_3=9^1Js#%Hf5UpmB2?yn22XWO+ERpK*)1+vD$$!T0ew3fDWvS%`V zyBE~l%pkQ}t4x5bDhu@&09OB#knh(5LyNr5f1}otaj@tR;yXi?n?Pyx-rNT*vGM&U z!cqdDXl}rYj57#ZQG8O@3TBjivHYKYKDdGG`CER)oVPG}=UX%aRqZAwu?>XCsFg7D zR`fBV)MjAilyLud6td6@o5MKxw=aB_LmouZbrLI&CxZ*$D?EN2(`;TNr z{yDVcQ_96k3i&1zX~T!(l1RWUYXLjz3LwJ*Ym?0| znx|m^;iE7KyZOL-rj$|=m4;u(8X@Fw;h^J5W2wGj!EI=--kF* zFiM2DwZHkvLD6NDkI#$wLmF{sOqC&*5c3nft1i9+TTgC`rl-D5*b=4?0`u?77y=t0&K-9i7=b)y+ zsnFvje;6g3s05O2`_on?QPb>Cj)9*XPqNqc6gTcv;5@o>lQ%}ub%EG`9JWuk!*rcY z_wjd@d~CUoc&7E|>sDqz36QEyFkx@OTr78(%|N{-AD6*irlY!V5L?r>QV(YafyHsA$g8h=U>q?6CA8GK5&TXAq8nIf)=b-&Cic1s!uh4lKHehw4o+Z(StQ6lQEJ}V- zSa+a>+*g4hBN)lPrQ*)|D~Y-4JNu#CVp#vo*sVn*h@=_$B{dT1iZB2;jHIsO) zfd?3v6n@e5s-5JS_*|-rj0Hq7b16B3ynec7>DWWJvHJqe_!jQ^WYMMWdj4>5`N18B ztf}F9?l#lYFmp>3|fc#;soK^w(MUD@) z)qIxY7#2XQ z{wPuj3&9Ighm?f_*};r6#$wNqbfT$=?eXyPqa1t59y70tetN8m6*g&4(XJTQ>0?B4B5~D!c=CM{zC|vV(spnwUBS|tg&Nzbl*uw6IhI#G&06rMd;0h}qQ)7&C$1dqDi@ShVr_-;v!73;5n{3aG?4?^{- z^t;m;TrrI^`?rZ8Z{eZmG;K$#YV1T`sJ-fCj(3P4&c!;b6v%9Htw-oUV8F zJzt=vGKf9M;w9ZMN9sk&Do3Nu!<0Tyc7^Nx+=ccY z!RIujIfJpg8PSm|I8AC=%ofOR*YH=l-_f#FYO2Xyy&XBl$E|Je}E8t5nlIl|ZSMkxy9WcqMlFh{>vo#Rlz6d}e` zzY+RgoZN50Rv@e?&Xk+!R|I3M;r6U^S_CffukS~=s*DBN+RvJ%lfKUO>?4-WyTVG2 zaUCm3u-14Z(<~&h-la-(fz=#mZGw93JF>;#xTG1fI|rp!+Kkuv`uW^2n!We7TzY8vSo$ zbKw$eCErYBz!<_q-5?WD^x0X*qwGok;c=r1@Q*5CG`HWpj0#NWz{Keo0($>2FM5?R z^Cn`Q^N>dH-v;bwFR6P?lC8LcJ{fB2*d_;?!?^?nwJbI!coRo{8GU-rDnC|PQK9MP zmRH_mS^_dV%6lJvUk|Ic%jasJxHZ9RZlq9Jw{Brku%?`LDQ833jbq@w-B<;YyXOwc=*{j@q_o+KbqUtrh8Ycngq*7nNMJ;WX z#zne~vPGY!bAlH+>r&cY+pjwx%BNd;yt_meNSWX6J3ck_+U|62$*Dry*m!2B@_Dim zY>0I|L-7~&sO%`;Vp%kt#MK%{@f2qzA)uqIqLhm=#JBO@#U4%@TbSP72e*Ca!2cyb zf>I~HDyZC&pHywy_e|{l+3A2`7bgO21V8SS|4C8P|4H-${MEdz$!T%-#2cI3RQ%74Jwtgo5CbK#KV8hh&)dYCX*r%tK%^1LXWPJ?-Ya zmGPp6Hz0^7G?y#s+7ePhnJNVH*imTa=tpBB9E&KJdZ@GaI7U#Rvrb^*8F&m z@|%6YexUoeqW1S%Bxhb>e02(V0Gh%7Z)FpF2{2pL^%XPy#k4R33=%JZ2`*yZ(wzAS zJP83$rasTxsfpk0>H0#3kQUvuVYfp@b{WE0=jSxqzn{~F7|>FmalEq5o2`zs*A3RPo;j{-+Mr?T)@NjD-}YpMF{*)k_Wa z@7=jSd^t5WwM;WH$rkHkqW9BEvcKITdSh>)e@;QiXq))VsLlhJT$>Eww;|u$AjG#d z1Q@G|9`4qfBtQGbTpDH6Bn1C_o?`GA5pjD z)Ff#n+Tpy`1g}SeulVvo{l!M;M(=u-N&O$Y*Plumv5ffBf2jFj>^64Of?`qpF!i9+ z)zi?gAbcV8pRa!##~uVIu5ku zLuApnNbID!ZMRpNEb?$N&3+2)yj#V^V!BQ2*c#nRMx&bBBFDd@$F0EQJDy7tS$LUf*q^H%fDL^)Hdbn zV{!+*CN~?;)iFAC2Mk-#Cj*++5n!~6zR;5{dR6n2lwF6PO+Id37znv7P}s=};N>1f zQ4j#y-ezJd`cY^7j4$pQi{9~jK;rnNAh<$rkZ7GzF;()@4urCg1OATK&$p$_B6zTC z>PJ+-L%|FA0pbKp&kaKLkkbGO`2*q8F$+W}ha+B~bnqfEFvs0UQnC|$U8`%RB`7ScHxCrCVp{7fh_5gQ>T|?R%fYdoRnM|t+<82u1fuL`yWlVc!ui}I!w_M+HVtRSiapAt{ zGh4{VSc88E5)^8eQjh1$*10TADtd;AFWXO#=$( zjc@Na7OeyC35j|>KN8N>d_B~sVHr7Mv0;gdu_996x1l~_xxBL}>MTl?RpX|kWJIqk z-@W}?@Nmn70oyQ=DIlGCJI}XXUB~9>5LVqp-pV%dlIV-rsOh?dFumUc8$d%gj^aEB zpV3XDfIAwD+e0Dr=aV9wwA8c9i=y0jsU|K?MjCh-`DOe3 zuabOwPd8CTWl{RJWnbq*v(x@iL88GL^_G_|t;DzFMk8*;S~UMke#ogYt{({z1!qna zX8Uw6TTCSN5l1(94t{XZ>5NC>oYyX&7uQ8+^aU)bO1*7l`h0Tw`}uc|8BsKeLuR|U z<`_qP2td$mLI_eGCVE;QUSRcQxx)Rx27yVRpog+d}7*2x&=74xu394|@ zhBYBE9CB-8*n{}qz;InIpTkS5x$d}h&*qO)8=F7rqGdIg-*r1B0c!|eu-*F+{t1`-K!-V`C>b(>D$aTKD0~*@)YyW;1h;%REN^J@Vb~Fh z1H0WuO&u--S3)pxjzSpDUw|0h8uhk&`yWX^t+s9Hfo?(D34a4;)?{8AJcAmxW;`#g zTy@&(ndW{_Za+o77AH;?wE!~D%Y_1V<&HDB9A4b@?cMsPd6E)_Sq*{0=y_D?)>5$d zl|)x2^7gZ!K%`pE%a;FzTI4}c?Z)sf&bQA@3-n?ugv~f~VHO=jx4$H8srQbNMnDlWsbK{~#qae=kXBk4RP*PyP$A{MC@`B|6 zLeK(Yb(9TALiSQ?NV`CCC~}qO>|_(<#)q0Yd}0L{u2uRudLQH%xI%%d$AVAS1|B<;&*psFw=C z^#Cd90(*NuR;#dYu;DR}R+g*~5 z`NHm@W#NJJ=LpkcgT&#Yz`WRRh1H7*Rnz@c6))Y)1c(v!;*e7Yi_~?v(8;@#{^+2C z){+#?)NdsA$E^%wk?cu3~eVk z(}xz=E9iSsyoG;sd_dMy!Z_>)qYq4vQgtg#*FAWM5IZGW(l{_b2n7MM2uH?yztmUz zw1cQU`JW!(T2QZ?U4q9v3KVjtlzPxXIz=zErWViMXBNwZyvWO|dC5Or#OUP#P)rUs z+$Q$`@)nCAG**4z6gv#VA7Vha$SEmS7yq{w5SCIby;XD**7`w;^B994f%oORljSh^ z(HdT~B5F579(!$MIVpW`A9JZYt+zBOR_Ys;55`Dc(xm`_0k<6FD_9at==)r#VN_|n zo>e;nR(6Vsz*=FMEx#c>;PS=o)*$_3rrw;S5FF&hSofhQG(w&TP4z#>ysH;19aZC( zateMCw^dQA`PU@)ng*T2^b6oM8ClSGq0a;q+b?f#P z910hX+oN-*hwXfDmnY=pc!vU8t6knFqKXPgtSas?yANTSRkTpBV0a77v7jbS8|rI$ zGS=GC*|ej7-zQDF6PI8x^MXci)o=cGI1M2t2}G@5O{W5f$&<0&+Jd6MbFb3PA%Eaf z{?-rO(XgS)^4c$tGL2a|4sP3>Bs=?idV!&p4#Qtrc59Zt&DbcLxGH=+ABi*{(~u1e zTAeqRf63_E;7Dy)Tih3Mi;ffTo%2!m!HbWp`|+GMg;-LGW0nDa+YQ813jx1%Y4RWm;!o?y;)+eOAb6~+ zpXhS26`n&aBNeP68xO;4ox}Ucwdts}&h-pQ*->J}-ImaVuwG>Xp+Ya$ewd0q+qb2h z8xOx$jK%#+U?p;U9X;}CS6YKY`Pvq$3QX=IS#UZV~2XY3Ul!K{|o6D!; z?Wy$$Maw5+5K8Gc>1S=VE!40pgg7QM_%-H8Y1>YNaEZ2~A7Mypxcf+VBIQlhPIcJK zM2E+Nkq1>#-_K17dXs*eZwfp}GQYLg6z&<7=|*iL^Y4ZnNcr7bwii`J|0%af>kHz$ z8d2e!(u3NdIrf%yVsLR9d8SC0 z57!Vv!V$&|0P0iwR5MCIMK`oXJ?O~~YEkVr*s7ZjxzL1wfqFPvlpagcCjS8qTpRv; z6iYfcy8>QvB<(hp`-u2cprB($S&I#_syA1E#ktE*M9uw~OOTzkTQ`;E^b$nkp2SM~ z_D4JZ^?4sA&*pYIB9OQ9;EK*5_0;<}UhiSmn=c|vHWy^8!g3QPMY#My!_!@yUXA;E zAYqhLo%6f6@n+qjRKNqe=x`sF!?fv(gG!`X@``7ady<}j-nWL+WWQ#I&FeS*>DWjT zSAngv{Gc#iE|RIcA;{~De|GSCkt9Y|g7+%$T>yV9Sb6nRnH5k{DjcX%JH~xX8u|OQ z9VV~y3qG^LSy!oR!^@LS_LdPXPP$C35)CIuX%#LSeXUH9!4jEd&-opi{ju`opM_<4 z2=mY1eJ`9uxspcjI*1iTa7hm#PMfxN_)3o69iPO&HeSW`RLX4Jc|T(!czL{OHHd-0 z+$8{)c)~A}j1|5urlW@+V_XdNEa-&jbEeea>v5*&67@}n^Xycq+Jl56AHq%d3Z}zneGAKsS@(b3qSESbi+X%Y1ZOw^8-|iQhU7ulZ8)-| z-14)gm(_O~spC745iz!KqX|6YQ30a1Yg}d&TKars`;93cZrn=+uIv55=N~+BMJ>z5 zLAgN>LJSW*@$md&E9KUmb(VJE(aRJirt%4*yzL#ii%uX6$g)&_{Rr~(K23#ufkJ(^ z`34=(Mjow5UoX#FVyNTjoIMMCp?kB<(5-5RV{}&dq!M5Q>G=vLw2XiF@G_5BN{;JK z1=r0Q`YVs!0Rq|R|0C=zprY=&H&7TEViW-ZB@|GkQ9`6)1}Q;0r9rv`q@+thky5&m z?(Pl+1sq~Px0 zxAc!d0QW#GknFxkpdn}c*B3{D#S#0d@9uLRg%{8K1cCnBrN#Y-kgvb`f-X9i&KhwY z;~EBT;fyVe@Wd1|++Sl$mwlu=+>A9#)$S4)&l>GP+VHf6dF|aIx-Bn-JG=WM0;++m z(_kDN(KVYzDVI;-A*Ej~d;Ms?12%>^hnndMZ+gZKPm#3|HTkLm*)h)A0vY@8uQ*Qn zM^3v>A4FWenKgW)-}95p>rQ-JI|P>tr*QbLD}R6dh<};l z8;4uA2Rt#ae;0BzRFzmSxG1(6njZb*FM&}I3%hQTY+Xawd&{QoqGp?1V zRqGE3@`I5-0$7qQZFlC9jzL@yTD1NnL3&c<>JYZ}jrZ6s@`4K<$n%O?TkFvKp9mPz zMTSORZamPgBV~Y`V*NyOEaMP1MRTRO29iJ@2?&n?5Y7^>AEbjXy*#omKGS*v%vF>7$^c(2bC4vfbGdgjIpEHyMcU-d7wXnNhKCpWXTF@C( znEP*)J-XTs0SyUjYuwy#k>~fCrn@qQy9%YAh@ql^_Mzh? z$z|``Aa!%(U^tQ46Dwn~1*Am>C7Swp>O$ybmI7Cvk0gR_*cXW%~_ta^>=1;b*HU zENcww-j}Wx185=P$1&Yf3zlnK`bKDi7{O_0QKZ50x}7na4TSbj$qyAA*UtQBDBD$E z(Ms8jRsh|aSsw{z0;&k8SAU3VueB;;_zS|5SHWoOy5rYAL&qK7e%r$VU?Y?)!?yKL zuuWdkt_HN-Dw28-F%YVVv=hykiz#O5i2K+{SMLO;Sg(Kmo_;C3*9p1*({7(5@%(ES z2VUm-^P89WlI*T#x}Pk$Yv{54G8|F&AKm9Wvm1ZBV6~hhrh)M$a%`Y|1n?z%J}H zpT!@TG{pzc2tWVWA-Av=91s&iO!_ZROXF~K1>dy3!D#78r}U>?`p8MJr166ynm#O` zKB9$t<`eBtS}$wfUskjc8u9+cnjd94Gg-AO-*yQ?w zepO4c^%u(?ff}_miP#8P;k%#1u|XrBL%cTQc)_2tM}!it{dc9zEoc36qhBzF)>jLL z$#{tIy`nu(b{mnvO}pw@^5v2ey&j$^9VCcpnL!gTUi#8yhbKx!0 zdbgXI!r5!e?a*02&yRZVe^Rf%Ox${Z!^>mj6_KPyHA8}JYaP-!XQG-3zC^S`BN!=4 zet<_?$Su3ZON(z#bP^=gPPt@9?#y&QQuJmAO)JrsqP&N0rDa=A^qR`m`(wDCow7<@ z_1w>kT`e{4CXSfmN%A#1n2uu%Nw@M;f%pSjR2n3E0M1 z1FQfXW1?y1d%dl;Ruj5Sy14o_N=G-8VJU%@y>2<_O;#K=)I%-o2pM|+HmN~T z-u-WZ8cEo<#|7zsiwp*c^i!ks1h=|CgqMd^0>PRQ6htdh5voP&#NT13hve(FEYq6P z-3)STJQ^$l3;UAvW>cXDpuh$NOvsdn=Gf9*_ffoNHemO~&Lw+xmoZ-W@`r~e#Jouc zy=^O4e8>_ALAy|X7~nkd+rzy&V1k;LMqUrN^gP*jqxK|&f1U0HgFB%59EP`l_Lw^P!U4zDcL-4F#M)-s>s0`UZ5Id??`#vVDsi6pcYpaY)K)$Sie4$2uFr-hR{2 zrrxohB^e@?5`v%&ZTlE9rxsZhndj@+)r1 z2J%SIX`)8kmaZ&XRFB$JqhbTp3;rPkxkEH&c|`7kT4lQbUp_sd58mD0G0S#lH500d z#4#|)?#F=UxK0)9%DxrGg>!k|q6svQrGb1CLs%z%Mst_n38>2gcl{rD9{mMScT=$V z&yRpKwRa1iQqE4C(GabaVI^8LU9r9Y*k4$Jvo*6U5 zBLDaN&=R7{Ep|RQ{LAn5iIqXr{@?5j5SC*3ztu~`Ez{V?>&{J<_wL;Tkn8za<7t7- zFq(zf*YGcquc?WnxbgNEu>l@O;|LZ~mgufiY^gNP<=F3vg`IyKBmjk{9HN=#hez7? z(EUe!$VCv+fA;a;)d@;QNJ>g}*MnA9i_1^Y7>x-t=F&sQ-?d6cKgiu@F6$MudH#Cm z4`eSnnL#Dce+rj8+o*p0n}7mS402yrTumh4kKgqXDKP(MHvgGyA4E!78EPK6R<5q+ z!e^y=erW7rQ$+s!VY)$6M)k$~HIv~kR>QHMN{`CxZ_hhhb$wr}wAP9SVzEF8?Z|>7 zILlM)kE{WB8W~~CL3RjWr|NHMkB?e&+L=t+Zb?x^V4QNjUz6-Vt0xsy^ zIk+OP-=?Ltx+bdy&hJpjb5Muh=xKSN9e9yFhy^k;7rTBNy{g+g6`IWd`5OxIh_OF^ zvDX`qLIVHig!nAc6DECoYPui@nEugghYLeHc_>P%VKF?sRxhvWKMhX}8B%WEVUNeN z8k;l*b!ZyS&Lf?3H1#j?ddyyOSJjb^IsrX8@)xJOLzFMt@Q32l`N$*MJinab_zCJgk7ULC*IMV(?AUF<>j+gO?Dgn*faXQKMo8T;>$M2Qrtaf1>u z+WFU?Q=e^0=7U~=NiRpAP69Iftit#wPaBM9F;S*CJM zOmS|H9r*}%!zm+JwEdzebF{`eXspnCZ)tnu} zQ=5aadY7`(t!Vj?hN)xqy3;)yteT0&U%@uRK*W*zc@2=zTg}ZYEJf!;BJA>nKw*U4 zi02hI_C=|}B~&&Rz4*pb<8`G|Ww!#ITVgX-)MvkDZSz~<6f;kK)63T*dM($hnN$k@ z8mVS8-2XkQk%6znbN_G@dU>(vzoul_VW3O*d}5yfxhm(v0^wulwb^7|l;`Y0=;#)K zdv6rg%ks6VoyTL&Ux}`9#1wNh$8;_{=vv_HntSm}9cf-jxK98u5{h>eHg#N+{uGAm z&p~$q3O)Wz`E|YmrxW9uk2X;*F?Dvw6H@{mYDI-frlH5vk`76OcF&_j?Az8lDh$~Z zO@rlmv41?KNc7%Geh#@gWM9(_1H#YmpaP&n&InVMd$-*APYn@a;$U~V(_ysYTJm$W z^xs-J3R#SjJ6Cx_S(nd$DC#uO*Fokl@TKW&rAdtTBU%FRD2zsshUR9D2aU}U*FDUM zA^CO3N!x{~rNFVlZDH)U<^g~YR$$OJ(N^`@^69_y5&Z!yS6Alm%7tQvRE2$p68C0F zI2J7hvCyh1Knc_crI@pP(WzXK2=_)*O}>S`BID0|6=qG~1Znz~S4Q~i-MLEq06W(( zm#l-#@Lqr-0kQv^*YdXZ8rOq8-V8luH9x1EuM z`Ol8;gM-!+LPEcMFtLT+ETP7+9Q39f_T>Q2ut=+F65P92I_^2e>NYw_3ns0NM_i<3 z#8P~49}k+-6C!hFsOfB5Gsty+JG_WXM7U+y_~`{I;3_nufEX0Emu{voTqZ_+ek3gC z4FppCzb5|Xy@4Io40co;&`~8b6r48ho_nFOYv4>4ME;?MNDeKTARPQTXN;OM_Mzcx zj<#WgD;!Z|hTr#F z{w?7w9^a!S=9v{oJ1^3%zN^*cVHa5d+AD3o4~l7D%9tiUJ7*@n>`&qs-?MNpx$EkElO@a{w`5NPqyK5o)P_h3}{lFHTJEytOa)zZjzoH*>FQFihjE+pRR@7 z?)kK(Vt!%vBe6VktD^f6$o4K$3#Oj^`}AXXIy(+-|0^^&0{#eR8TEwfHiCe>P*gt$v?mzO-c!@-cI+sOuB&E#Mby%@3lYq zk)kB{8g=t=czr(?p%uY?W6Y3j+lu3tC6AVdjNrykNtRsrTpm8}StN@;zU4aMc$>*d zB*S%^0)H4G`%KIP`)5yg#+XoBH~YEiMg?48d$r>Gw&2R)wytG6-Z4+lBMeL| zLIj3SKQXSfO=mY5CRU(GbImIJ%1V(;SF2Z8VfN$Wl%(Zlj;Q0j@;GS}&eYwT*p37a zC!f>T@10&MTYorVU%Q{sH5q{9JNJ3LrCR8k+tcv$)Bfb+vy;U+ss|{c`RXQ#E!PN5 zJ)v>0w_^H=KTIj%UD&%*eSi|YYfFGFvUeWHpOx&_ei;+XAJGgl*V^)eP#H41*9Osr=Dw%haW zLKEygCq)h(z$2xfo}EYccUo(HHP$|uB2vou+)i_{(O6h;c3yhsRaRJ2*szXSwtA|6 ziw(Lawp7y5Xz=ji!@XpB*~&c`?vxI`8%ghFZ)FveKLb)BL-F<>?Ib~=*$Cl2yTiA+ zP)DE}RpbBAWFbLSO-)l-S^0hw3Q2hLCfsuz^lP`*UFNZ<%*gockk7BE>s1*SIzNl_o7wF?d#d<(60VQg50 zWYU-mrBmuhR8O#cmi!z%rZSYJsNK^xM4>ODqBE?gnFfhyRIXRPpHQzWvpGot^9~Q8 z-VPn_r>)s}%2v>inoK(No_raZ;BAle!bp;#myy~JTo*d65;=YyN2b0vrH}n%`qEiz zGRKlb|A!o-0~`Lgn^f${oaAM|`W){8z5>c=ZItx6^N1*ckP(oytptTYlP1;+WBCOI z-*9$gbdjyw+8u#H?#E|sy;{ArF22G0Z6N6{7C>`ZX=?p*h#URlJe7UO@w;R5 znDe^pMqVaRm;Ge>kz*v_zLb-N-2U=?*7eo(6RVZ6p2|jk$8jx@Ng=a(!Z*=~mhSeN z)t>#uV_B_&koUNy@Y#wuIZpCngfesFrq3fyC}W~rtdd6cAkMj~wj7~n@`|V%bSFW` zd2$ES!_BSk7qcuT)Kc(dQ+*Y5v8?nu2q-$*sVMRojNrCD!lC_)LJaL&>K)@82NVfE z102cXrZd2_TlXs(28=F4I4E6pKU$LadbUx&9ipnLI^x_|HU^qIC$GLe-;MFu{@P)^ z5Mo`qR&sAI^!(r1%f;lXrrh_?uIFJj(V<{I>KzD8O5^769# zrEq##PG|=syZDf3EbPb*%x^SmnM>10LWFB~cUO3Gp|Ea!StZk+Ll?h#yl#x35Iu!-zwsuE$xo0zN0c)U%(1W=gR_VB8wN<0>miNDLbkX?5O>zRq%I&ZST8LYeYxekDT~acDaNcmlEt}fVXvT=^~A{ zs{_Uv$3-)Svd|xVdE2}B4K8o=X;RlY`Gz)kPfd$;8aJ_s{#T>c{+x8c5Bq*L3lAAv zLKS3o%$qqd4|2aBz!5UMSH1X#_s;r8`usx=|#vDaI=6EZhJ?D__QpDBG;{DspAeD|cwzgS zo3U^g$zv!@Z(m#k;3bU~QS|3h@NT97*VmaJ^8$7gzONOfCNw)UvprPCWz^iphNmF) zy?M`Kn94JV`+>%@8}6^N#>U+{H8rP7P+2{rv1JRga2qbHbpfU;!sff=(ASLF;v%dt zldm?aK6K#>^4xT5O+bR}@H4mlyo^`AHHlan_;Vi_izQxz+Jy=boecsl(6Gzyidq)R zQpY-D4TtmbvWKvF#gTGzl-25Ri3O5j&XNJ9rc@lfJmqzMnh8kcjwFQX%_*R0;FvTO zDEXMcIu&n0TNueCFlAxseSzW>X%L%%JjO!9{9RhRavP z;Y7yec167n^}DVhKXqy$MiJefWoJ>ZNXe;M$EnuexRv^%^2QBdZ>5iP=6`+-H>uIn zNzi*Q6_7tL`}U>i9~Xw`I!%h{tCpp!z@s6<$2=1I{qqa|26z@v5SW5UK1#S}{l+8e z6YQB1;iu~T7D7kGi3F{J1U9%=@(?*(XJb{Gt83u}!r2R}vG$pR&7*i!H%q&yh4!TI zEyQC^ritd5!X#L_&6?`c5lMxIux3StAYaYeDDjRPmg+6nbJGSLNo>=-6He^137~5Z zLje#262dh5Dx0bGI+f{Ah&@St8Vy3rS9@?+c*#hEMICJ_{P7j)3h` z;ntTv=#^lf>1muplesRpY<=@+BNw@ZR6SJm4xLY?CQ0X1nu6}Qb#})N#ZcAkwilhX zCC7X%kM|7aAU#TW*b4qxGQE@(5rkzc zVuXx#!{s~r0uhIYeT`}beVu}?Vo%EhL)4}f5q`c=T$M5hZBL{`gkg|Cq^b~<$Q*hT zO3(C?o_WQZ5<0wCqDA2)?>OiwKdTV-0lAVRAFSLWy*%6dQPdN9dv58b(m7TkXyFhq zc=+OY9p%G@g2vwf%MMM}l)wj?~j!Bc*}zSEzRY0+eDw4$bCV#!S| zv=YUuk}0{5pALsg-qWt`m9rSk^5JUc1Bbe~_j2zuA{b$>@~a!cw`u>GKeP{+#)8-Y zZ$b1xkTu#Lsj4yvB--TLS_#@;jI5&n-|rglDN;iK6nG>G44GJ48(7%zcz$`BtgC4) z;dAe3Q&2(XeXxfxPsPokEu8RFRU?w=RHwbw5kpvaU%yF`QBk@l6z7s6J-T!iXtgi;xiGEK{@?#I; z-XgZy_TVxCk41XavP_S=m)F6{6Z#W!)bq8qSX(&d_^emal2&+04ygw<@O-H&HVUJN z=cXKobTT)HPp>Ev1~uv>bbSxrdiC*G9S**XGM}TIlUxFlEu;=_W#Jr>4|QlExyH0~tc)3ObeOKs3*E`FnZSX4QPcp2Tkk95GDBQi<$G|i zy5z|7v1*il+G)t$82NIWf2!tk2k;>5CpkGij+U}K!gL)P+w=D33OpSJPu^0200|RI zLfP9psc#_51|2V)cRtyXJTr`K_si>*pYiM!3YE}TAyt^`pg$(5Pnq@+B-w2-s zRyGFlpl^6@$U;xm*kR?~rr#bn3TLe`HYn=Swp+c9m_Dd+s08vH%HHqnk@WIOR<03) zXc{W)g(60fuR=sob25{1W{mLkb8G8{$6Z1QvbJil2>Pswdnycm~FP5#qywj)E3ZZ}eooB3FL)coaJ*`e&`dw}x-_Zmq$&e zh70Pu=12_4JL_d))>td)$i@P%?PicmU>Ay# zo0@`YD`Rwp+!Bxxd7(-AWJ+Gq`(0xb2_s5JfEndcxE)bmw9%7I4V@WB`wz|HhKkg{ z$v?BxuHA4vm&`j7%L`j_(=i;38O%CTgTpHOVp1zB2CH`)$mUi|+h;@J>s}^{+NY~3 z4UFbj;^HC1yY`Pdj*^CYQrZFt;?=(O$3!qt&h2ttg&t*l?b1Gp&80rASHeiW>Dbtw znT!eBLiG?1-oCiYKWTw2@={OFBmi9WBn=qEzc&hcw^S>nfP37Oe_;|oVUw@^wgLuZ z#)I4=CY^x0l(yfH#eeTord3@%tv5m&>xd_Gb3y7L!@m4>l;pM3C$PtTJ&TM>Z6?r= zY*J_m<4Z~7QD%MdIZ&1zYo3>0dsM9DBit7-el)GKV3y}J5P(#7;}2QR3sF*$x6YBJ zTa(;PbsCgYfiu5b&Sh;P*v&8;98&987Lc|mt8=eNvyVuvOta^bo0F8Xc2IZf5!!dy zQcN_f=T|@NR5Ixt(jJWNEFZLUp6$gsfRUkJB;NSCl^=y3eUS%#d1mGI_V7l$xBbXe zo?r6_4*cMD{CS^M@yJI}IOuWH_`ELJwNv-yjHH2UOHpmAWllP2GK|SwW=*pq-v+f; zLGt*Aw$m9*PMNZi#=VOm2#-Lvg$bsFZmZ+C7!HwhI6v|W;eoCJ6ELw~TSOX^ni7#+ z2(eaCbu3qPJwKk>P*3ZZ=7V(u&44R$oe?BI(@L1a2J@`N{%ER73UUO*T`)%384EK0A3P3cpd*e$jZjMF^`Ke^!;984@=6 z{@v&RS(;NsmPg{$pyJ_O^y&9`d6}@6cw_xD=XH+l% zp{On*bV-rj=W2OvKxMkmWvmOQJyR~$;(Y8xV0Comc`=6}^V)EU-Y7coa@z3hq;gxO z+zYlbLZO>syp90hatJuDC+sd{=wF9MF)=kuxl?aJOOLvaShl|g*y;B0a=Kv^j`l1yT1nZx0NM<2D%{` z06%kzlZYlyQtKfs%8LD=sNM$|^5t(Lv zkL#|`Q*AeE^*x_I-g!*Yx+U@5YGK`Z*}aoAc;z9rjy~wVne~us-1zeKacg`7P1}VD z?op}P-Wa8v2>ih(EFzBho=XMR6VbJBM|p{sd$16xEL5icO>|VL*}%{w1f63{k(BaS zh+cZ?!*}SzdpHLhR#fPoIzOE{US(VqU&yg3*d*S~i}b54oF?^1X7W96kN=AWH0KoA ztHolHyJeou;HaYgWy-zurQ`Po^_O?1zr)As(6_gQeM*{VLarx2Y-+eJH7cctN zP%~;^To?&43wpO3_Z!#*;(}uBeU?OVZoE3*pImw`fd4XQDd!Aq+KYVTO zUs8$rFyncr+fhwX(R^;s(5m&-6RVR~`vA9$KKL2hcKRzViT=nAdUTFG^CsX23oP)h zntvZ{2Fc6P7jvD@I2#DoRX3I&!QairP4RzT(W*J~S zkYHLCU{-GqQ6uP|&55Wo?V%d0vPm|FvOpUa?d&xN7XU|e)5F}Da`4?~-_3!lWkz$o zIn6m{in5SM60-CXv!<$aeu_M`o<0j90^tMw&_OrK07xuJemaNKPzW-zZa#0C>RVMu z$i+MnzKKK}uz8lm5rm6e%uvr<-;P;&fU}Um z_aHgw#-H~ERb$)&xSTsyLf4r|;^VulbAGNL)O4ddp?kawGDUlv`@ewPx}~LM+4jO^ z+KLL}lc!vbAEh-NB|<-F0@XCW1sMRiHPs21{|NC_CUH-bG+XLZN8gp`>aQKL0w8Jq zEuyGH*Rd)$*w=RFWzIUpf~0sG$g#w!<=P=*sg^20!(mh>f8W!As=aMLT`n~MPYhPI zr<90^Z~(Ed9ZUp8nLUz(edk~{H2&yadz$^q%E}rj-BH}GNv|Bt>LeY1@O+$CSwBRL zsQ-{(QbfU(HM-M{B49ox(q{mvs;*-UVqcF!f;F*Oh0QQuw+P7#Fqjb^c>U6|{13W* z5b3A?k9BK?LNsF~W0Ow?vI=r@M@Ju!qh9<%)@)LLzgH(M-_f}I9(YC5P%@f7vq+MS zAgtbWwpvi1m&*E}rWREixK%DcXKaq@6areTN?+46TDOciXI4V?xZi&XsVT~b@%E*S z?hIEhCaiCfl&4CnES-Cqv-A3b}cLkvWY@5k;JI0PwV4;+0lx>~v@xecPETteP1CpFiOYUIFrUzs}(@YvKzF zJ?fz_WlBXCmFv4X?vX6wE*7Q$)y-_ChBD@yml$?vI*Z7{oRn-sk-x8alHlePY>F$( zR&o;mp2Oc?`54^bb=}F1ja5}u)6mkYlaH0D)Vi0mk#HIA@P%qSd1EM(uFUz|$a|vnj53+5|b0cAFizS*Y2s<;!9ANSuANsE%hO zjZl&d%VqJrTTEZfxY{2l)80dPp`!>jnlH~^O8#e5K2KrnOjv|(UN?UY|E8v_Y`C^I zV!TsP-b5dT3sFYM_x@7AMAkKpI_rVaFH4M_4-y}u*EJQoOvi4a>b~0QzLlOQ61qzf=)Sn&H zOO3gF=XdmjFu-$gj{=F6jY4EvJ)&!w0b-BTD1Rnz5S-A5j(cw0;PpJI9{m3ODA^cU zGhSI*+8-Ae=ic9V_UQCSfumj;K-HI5Ry_JW_bafY@;Z#f3{l@}R&Pd7S5$-gPdM8* zQTxEH0N1fWrBewHvq^rnM8+bx);G!Rl^(uZtp?_1pp%Xhf@)mz}|n_cdO|FtFP|GeVoeMYhU=`FEA z7jkrT>>jGn)Y|w2r|pRSHZEKS_XH+nK-!3Q8D?&fRZ>OW*ReQ?y^-3{Vmuh#ip)kHlEYnroH2M*LYK} zu~cC&1ce|72s4hWz{WT*@;Z0QjJCh8K0m&=ZmCT{jQ7Xt|G3TGi7E68VRZd}4l;V+ zS>9?>IfaFs&}}2u*}8uCcYzz8`rx<@9}*C?CPGf1Jp~_W?!_~E9eYCRk?KtfO*Dfh z)UDTcl{+GJitmI%?%LGMT|a-IY@Jn8 zDpPk3sd?nG?UDi>xrDRI({vcD*CO#6mZ``dq*nR1 zlO#QjlMeb74UMikOr}ePul@xb)!G2$7M^>QPD7rU)*Lrc=RAh)(_lZ}{ma-D_0qB4 zTiaiIhChXN64)Q-<*dEb)05{c}9cCAIQvFSy}DaD<6VJQYM-%lGYMZ zm=XZ7-E&M6gzlR`)Bgtn4HPV=_`nHrThA=ir3`fe=&P!(uE*Y!)c*0;^3B9N?(!m< zI~DiXpl4>0G|)|OL!;qNwCm=Lcnf2<{^MjUssShExyF}2*qhHYQvLDYJMWX?G(he= zH4~pXbDALeeqXhOmoN)xX0`Vg;_Q({G-(*`PjZ+L5R`2#*wi-POyNzX zmI8_AQM8sG?9E$<8i^UF%a)OH|Jf6^29hL$OjRoq?bK;9Xd5GA`wfTsoI)gkA{=xj ze?jBXs--x;7-J+Ivt;8<3_C);4JtQYP5s3(EU`9;hA_`6iuiRF@;Y8JF-kg;V5RAk zLGOH(q5_xoCZ>diTZ=Drf+CkyS}`Ro1f<1Rr(67lzesHdLF`n%KiuUCSxEMpERsmK zGk2%RYNt#r(x4-W!<9zY~EMMn-`P z5_^)JB;zzZvoJYw3v5XYpF7tT6yABZi%Vg0!<4=ze}FiXSf#02B-jfdhvLGGqg;G&xxbMEFew8W+{psMG)LHukWHKAspv2}>FwRc6-mGeG2*k8DsR%&^ z{j@l~Hdb}~40^_BCfOnY^X+p%@_|I3s%v>^7&9}YWF9e7m{iAcZN5T!ebNWD2>>2q zFp`T|I}}Wf@jBd7@dCm6sCHN?2K6^MoN>`N(C9x;f_@w_OrcASc)Udabw1Hn@I7g7 zz_`gRML~lh;5Q@|&5))z0{`_cCbU#6w7S3N6XVi*rAxQ6ASxt+X&6x_9rpO;LWx<^ zx1hfmQzS5XbuMW;Aj%C<=Gv&Gf1N9Be2yv%se22%75@jGPM zCoW9I;(2wz!_WJ&*rx^bZXOC*Fy~h3w?OKaGUH{mgxd4i^7a|SBwAQCG0gy8%5B_9 zg6iZcC@4@Yn|PjvaXna+r6)nijaywFpuF=->vlR68)(?dgKyzPt)o-@l4ga(n)&NQ z#skSie0+Q$0m2XG30Ae1%!4gyYlwv`>tR0VJE|c*}#M zk?#+gyv2Q(Vfk+%%C+Cs6Wxx#eR4P8fP|01~3_Gu{lL*en}6eO>svy zAm)lv%carQbYHntZvs$>>~)KLbg$!Y?7t|u<#gHW^$ zRXbOtKFn!soE&iSq&mKI;{YY^*?FDqu-aoaqd^|cwH^L={x$4t z*oo_y6F0sZ>3ixA8>i?dV3;gR%Q}dT^ z?BN{LpQhb*j`@-F+a0mR^|Qn3KkzZJelVsWsG&QnV^uxnz8}=4`)K>4*!0%3@;ZFX zU(?(&%eZYVC3=_ej7AP?WI9NN*}&M?JdaUc%O!@nv#ZtP+SQH8OC!g3);5SI*nr21 zg?avwTle?Uk>p{_hU6g*C^faS+W&(WT#WeWUNatgKT~6Q9<))T$s3YKABE0O2-Y@x zJm-7dcPo;|W|A9?0tlLn;HO{TfzDkG`TEsLPVKTNS~LN z2C0RRcRHEpc|mm4@dDL$6j?Mm9>Z}`BfTOdDeAqitK#`K7nOdHqx0C5b98(?IG{3G zT@uM1mE=|GBq)bbG z!2q|zA4>((^~U_`SDWLxPhX-g-tgS7+e_SVXOKCk$lMtI=!YZJ8tS#NA zaCanr`&9ZQSc}*Gdm#j>(8S8bQKg}xXPP!VsEaErgBsAe4nDX0lmn;|X#x=;52Ey| z5OKC$)dD@p**-fzmbWyAso+ zWbxeUyx7bCz645ozrO?W{;+f(e`5JkPU~ z@K{)$98WiHy|4zyPf6V61iy4hV6CWW{nGgZ_IftfdN}J%fAb|8vJ&(Vjk9u_;zzUV|gnN2LkxTD8)tA9yD@Px4us_9PO(;a{+~csm08bsBil zp|<}cumQa2aeTIYgskkUhlQrK_mWDky^L%nY3m~Q+`ut-5%qsg*L9&6!PY1D92y)a z98XD`(~oZ-Z`0tO3mE)127zKUj34YcWqunhn3Q+PfA)dG7UZZoJ3qg>u}KzB{#;I^-@AQ#%)AUN+m$}Q@ zN;X55Opi2k*(#3kxfJ(pB=&5Z<*ITdxX%e3;ERpDr+)_{LBkmLo>KuUP}dvpKjT18 zBn=?}=7Kgak?H8T0?$}cKe5Tr#)QkOAD$F$b^xy2l4yoQXTO2;t7DNz=XW!<6N`w8 zcuf4zA4Go|v{wPhe1R`baj8Q;GjqRic2=!x(45*_P7W9JFznfCZwWZM0WI!~W7|#zy4amGh*b_tKwV_wU$tSP^&-amJJ$%$<)24UJ9^+SSTE zs9uE+YH~(y<^3}9bNMh6APrlTiaYO`-u$_lhvK`5{&)tx?bgq)O7WcA;ut7mVxG|T=~6lj?`w6G7~qDMBRpIr>S1(Nv4Ki?d)87m;0Zc zMe+f|@HgD2&jkn+^8j>Vl^(|D8PH&k_?C+gAUyZX*4`PE}>lyTm!nU6bqtTS^Bg^T8?Is&0Z`${dpWeakwyBV3 zzV$9-g$f*w7QUe=t+z)P14&~g40>_y09>q#Z)sT&Hvbvml~`|KV%*lMt-!5uW+7D8 zd7^!3zJ}LO%W1$r` zbF4u97lHC0;d`g> zQ?|yW<&}D+7tF6}Dl4kAw6x+0_}@Wrq)*18muP|NFp^KX85zN(e32CC(L2=W;N|>Y z2+0V!$^Cak2oXGXGQbS615Uj}LIQZSzgOrV`$;1QISxG^eXQXZO>m0)4pL9ObLw=o zLk{xq35h~(0NxpuWx-}DmNdSL6{y-=^Xyj52`D`c z&_5>(7dE2iY?Z(AygdAnNvr|Tk$_0f%q7j-(@K2udo>QiPFs1>W_a!P;R zKHZ#{lKX-^od0k2eN{|ko=SmzC9UDT z;n&}A^ewIYn&DF5gY8rj{a##>9K^x7L!iUYE0q8Bp9smIn6!gtKD?Vk^4re^xlY+_ypb_QodMP2==tZYUwrIxv&6xo$cs@~JIdR zsL$n%3VmK1bIOqDM#*bmU&+?|fE}lazgx?Uhg%&X8Z&A}Jh#GcSnscAt)gktQwI{< z=(ZPXxl4dS3Z!uk#q?{W z3?kSdPtH9#O+S|2k6wQ;VWVcm7R>h^mo-vOlR2_{zj5E$deWM@0_r?z=sa=SA^gSk zOp)Q6_wVig8X>jvd6Uzew%L$fq3aJch23;(eWkrO+j&vt*$X^DF*&Vjc{9lwb?}zk^MsBr7U;O~ zyPY4Kjz|JYQLO{Xcc*Eca!KxEMMgWPrj0hHJxNve3uEq^sh;YcP`2wG_gWayAQk52 zpdIO;OH_;u7h%Yb7R};5d4j?)BnVB!`;U=LF@qwL;Wi*$=rrAo*>pNX;APeWKNq#M zwysdl(p>v|!^;YOy7W%?^q>P?O5L#O+pvv{-Sj(@$xVM)1)iVJ#HCs< z2kIryevgdfCz$L=K9y5|s;ZF12u7+mjoI=OzYY{=gjzNR)0n5na)Eu z>u*&}*2%RS!g($|ZmZon%9U$R^h(zN&s`nxcQ;rz`dNy0T7+RoiktFG@uVx`iQsBm z!CjSldPgDbQMGK?HL_uEeE#(`nlF=jU~0Zc&!AT9UEl%obYX4l@Pr60 zeS$p456S)AGSB4~34YTy8C`ughbB{#Fa3uqLne%=d68TrGw>NHGu7fxT(4AL(7q4H zy~cg&Y%;urGL^{#WcIA4@t(7Xu7%eGa7nV8cd1Xa>6DqqwkwK8ZalB~{N3{>?cPaM zVXyWx!uL3uiOn4nJde*asf6TUX%8oVF7cfH=TL zz}W&D;lx61j?^3#D5e>kT`y>zkpv(I8E)al9GN`wjMl064^AV-;j6(sA;$= ze$@Bp)@$U#!%UE$AIY@CKWD?o2X;3c9j1voD(oWDMdL`?#FUa9q@%N#^+`AbB^;10|eI#D0r%&S9v6$Pp7r1N>6wUZiq z?tS9qO_oiw3aWxpVtm`lEV#Ah{^~E|vW@CCIiRuXw3w5X`V3%r3ha<8M%h>i_Ki$X zcM$O@<%q?6h?0BFl(-`zY&=t0&uX2Ku#;U;x)q^%Fr8_u^@ww%iAWY>Hf}ol%yt43UfF0I)3vsM_54JW9o`gq+uuL2sou`h;ESGE zZaRERvl+_pB;!Mr3^rY&QqC)a7av|L@h6s-I&`+nli9c?3VU=GeL-D6lS>CrH8xhz zAe46JBC~fX(dFZWKRptD0xWs2w*Qx&6cw@tV# zO0tuE=Xb8zQ1|_Le}DgYFk|MruGj0l&iXvhb9WD1O-%z;mbMqKK`@wwl^6CH-8Y&(oERGK`K>?{#Czw`UrZVr#O&JYn} zCM*%}<&>UmU~ZB-VI1adx5j59tS#pS$aE|W=GohX+HY`}9bj{Ct9roXcTM=zWHC^r zRkvJFh_sJgHzTwI#GkxGA2h<->zee+e3i(>RAD;$ljJ}RyZ{AV-dUSsPcdy{o%4W* zFq+)xKc6()ywB)zx0b!!)>+|l!0+r1P|-Uj(Y+vHR5Z={MVuV)Kp2^eQRC#GpKF2o zQ6SjHcdZXXRDYF>8ffi!w2$3-bD+4$+QmhvVr5b`ds4EVaC$?yGwo%>K$+fV0A=95 z-&}6%%gsIKpXzj{fc1RMd+b|OVC~Ju0$Kg7p(piEITu%T3xg0H+g9?B9XR^}vC7^~xXO#5vIiDnVtdRAGn6qNw%+ zHSI1Jmn&@+_3(hnb|X96))VJ9il5!T!Q+O2=KdX7;}5PGGCl-ovp4g}FX&d15K8IqZQS)q?7EeOP=T#tIOOo)*mwB z9zRHbpgBhK07q%9cxTab4|wNAyVU$M z?!m2qTgIaaU}|4(z7Wftp>%x5BWO2rb;tSX{2Y2K)lqNyOl$wTud8OoX{aUTlWos$ zaqo|!1t=+1N^2XDX-s;~&YAtqGs)@gcZ&ML!e$qc-lNsve|o+ueLDY^+xh4BiX#H^ zdu{vszkdDt>ssI|da+=7cUiH{7t!ZmaLJB;$r%aF%;CFo>u5OdCUsnCh`9Z%9*ldl zdwRg~;lTq3CUIi6?r&M4e=NN;BLeq?Px0R5+;)iGZECFE(OL2KSVwTtg3{rYfN)dc5&P0DqsIf zT&t3*Tn-xKqKL=DoalL#8v#+8^;(acqoD(@gl*p1buwVpqp7u*lnbqdNBmPXr1I^9 z*pVZKb3#V z_g~`;slFJsVg6ZM>%sTfE0L|b?^m1bW3A{pz|66CRHQ!NGrzXBcFH|brX4yJgfPaH zJ<`)McXhHqn{@Bk_v}j&#^vD(&w{HNf5!ZZH9O2)3&%QoS zJ3754`D46UqBn6U*2AGMM5Oc8TmrOOCCJnUP8;UBq~-guM@EYN(P?ECw!EfaEq3-w zPmKU9{Aj{#Z2oN4WwnLkIx)v2`}!fvy-yxB+!@zaU99j!erXS6b}daj&->vwGE&Y7 zk_iJZA!8u3(LZl4jN?g_re{utvf$i7LzZBxeFvme@{v_D^~)T)gsQ;lilW z%&moq@&=v*lxyL*Q*g8W5OwEh^d6m zcb__gv8vBJD$gN3Sp5n4M%h>D0iR$Ya=zp@y&~W- z(g9&+G7p&gV4W8Ar|KGQrG53U-JAJU-%1}3+?%!xA3*Jpf)Oq{o;fh@pmhMyQL{k@ z^Lu)%s+AQ0BD(LCO+)JEjOK5pVh4;vt3&;C4r{cPx8%B>pqEl^(0x`sOGk0~ED7}J zQU6rVM@!L4ho}Mc4z0a zm(Z0nMQ{7<x%rw?8{eIT7rRJ>3n~n{xKU-Y;eB=?8evwgk7Z-nIzWXc z?tcv!?M5I_Nsifde`oUHnC6yZtrURMuN<;)mHkQ0*E&9sNy2uaJbyC!|1azGM26ZWT_z9;uAqXI+;x=J%$@euXnT`~8PbSKlUiIblB#@te?X4y!L!+KuWZGM`){ zl4|9vgKEfewjZ!F&?hJ+Fk1Fu-rVW)+ai7j0D-C_Ch;-6TNClbT9>_|I-VMn8z`+; zLACvX4TF|jFd9`#(qnOUyY!UYw@5gAO6HA}`eSYRjp-E@!IG>7g!y^2oy|W%-(E7Y z)S4u%{nFyMt(w^clsxbvi5bCJxiFPr9vg%V%9 zs!Dh7J{~>X8kaCaI4rF``(vuJA3|f%vAMwsZLD4-9g!$IpCbG9={?Vv?%5YdAeLG& zaNPC*28aKLw6mk9+GeM&+=aty(XP6sK&Y-vJpZsNtJqB2O4+j`vRMU(;H&yGc80mV z_!U}J9h;sD$O*fsdAIt2}_K>Ay`l2^XGl3qD@w!kf~TT zD%$vb_RCny^c}NcodV~1T zOjX9zpzPEg?R%Te^D`_SbR!rv_`k8Qx;5MeWCz|`k=Ja4hhA% z_US&iw7ifWHv3b)F?UA5wJ+u3w?lakPWZ`8$3D2(+GaA}VX|8pXiP-rpX2}o!Rr>C z2cL~bJpcaY>gWOv>2YPh7>$B5H2ZrNbVn>0JWCFr zw4|i6@xj)M`rAK=cVG@! zbnp%91+aQW}W0XZc zY=XXl!5+-@&qCIgmMPi^I#AOB80{X+KxL1pm0{=6{-bm8JYzBY(-OwDbpbe@mkxX7 zf1qVxxb|L|x_869vO6E+_is--eLhbtzYl!beW3}FDRGCvn~CvYpXEE$k#Mgk9)SH$ zhwj~-iVfqht*e_Ui0TSLB6nD9hS5uFDQ5-g-E2Ec7E=Y)ww7eiX4xlQklr;{CLVft zrdM1f5;nu;HP5H3W1NXXFdal7F<7$hitOxfbm@Wospzy&Npsh{@q;Ep`ANlCyog<~ z|H;nWsp;P609TK(yCy%&DxD|XXWK)29HlFIBqT0QuRb)%%Y~kFNUR>49R2)gMNfjY zt$6-)h(71#1Xo)PH7WY}+G~v|rMLDZLl6OEa7cq0z&Ip>86>cC(tvRR1eK zTs~Ti9_%>(Wu&sc0%R1r5v~UWM7@CY7eY?*nYU!Eicq3P)z`1*>uW9m9`(V^O59s5 zb*qczK@XD%Nre`XvjGPm9nCV*ofKO2`G=^1(+YE6T6i)HZ zJpIbQ)@xv92X4=@%mc9Qu&ceihTfvhmp&<@k)7h zUiofs_Q8_7jz9I&6bYi3z18meI;SjK=ff7NA@4OTIDPaSM(XL+sg4cO>DHaCbD^P@ zwg;szSdVi#1?jA)a(CZ%%R-wQJs#UXJH69$&bqos+Ddb(QjD=7uz`eyfy7fh3eK|t z0Dd6X0N@3r=w)oY;llelhvLqdcl)Ex>iPM<{J#Iw#+`fnh+2c{zYz0)K&%wn&Y<2F z?owMc*(ANA_8Z0Wl7S&B%O8jU_xqh112dVeXXmy{b#f$1HRuI_dT(osxHMC>Dewp89zYlcH^cJPIok zA4dLcu2nr%$Da`q z-+{mfA)g3t%n2f}gxuHZRbn7SY1|Rsz9$r;DN&!IuUaMh@VH;c)~H*x5xe&b9S`Ov zM4zQX*LZbMaxc!mKTEpLn5dNBuc%}DFec!WMjK^b`SctgM-0+#%JU`DIP1USU$3a2Me9eD=o1{XP-U?A0 z%}ipQv&zzPzXwDi|HyD!d7B#^3L~7BldCo2&US^oJlge4<$MM$RdZ%L>jx`Qm1t8m zCnv=xrYOUL3MT$za&Ix1^J>3O*7TG=eKOmABa2b&Xot-@&QvD{o#_IOpk73dy$_33}2h5_rzP{VUrduD|LtdZz@^~ueyGylL$d^sf z$x)mQQuPG%+ZZH>=w+<9OzQ_LaTX91LX$qvc74A zU!$M^nDqyC(HyirCpq|p0rV%X>r1nsjFs3JD%9={(+iXQ7KpKJAmnWrk&X{EONQIGUwUZI$M)%mq24Op z3ILs^BoYaSSxw1^g2jBt9D7B)2)OlW2d%&A85tQ3i~|1jl(lt2d3Dcz=-bud+0iff zMjo8#!r(53e#yYq(Q3gxu}Nj*o{C30_3EA&-phLpoEp<@)!8!p0benjhjLCON)&Gv zIq$Q^ULap}j5rSs*pcqqI=L1qn*zr}zl?|Fqx`04fXm4&`$~V6Wi(v~q|Wpl9nOE!Pv?Z7_9^#`Lx1HU^eHJyd>i<#4nq8#>QIdvoG2F+Aww$B%}ZLiw|= zq=!H8$>5F!V|ewm9O5hw@^U$yVB4YcG9fvy0sDzqz=8hS1dRSyV9<=-s7CnRVfO39 zQBpGHZCrf(E8s(Udhg(~E;n@3QGz)1_lpErZs$%^i7W_;HL{)PZ#1tnwD;{cCQkE2yH39PrAh=A0BIWGj{f@BMOpTGkS3E=?aUu878Eu6$il;0(=2x2@iVsw zYpl_0i_IO@FA&577#jFN?MwdBcN2#Pyb$?S>S}bIXd5p|-yAo&`iI+U*KALLBVd3w zs9l0oUG3=*`>%nuCO~}ThP#Wh0-_xEx9uq~cuRrj!`6C!rgK1CD{(-&;mhF9T%Zmr z8+g;cru96QHA9Wd>dA;U5!SGu1V8W>a#Hf#@iB za>p1Odi17tk%M58K4DP_4=URl9ut(b!Hk57U3^UFBOqb4N&klpC@2XQai=?pt%(T7 zCWa7kK^E*!?w&X%CtD_Na-!d2`zBA}+lPFQ%Zckl55VAaRFwV-DpHY%eSC@px)kv43X0|DHD?6q}4+Fz@K z5Sbk5+NW2kEF+<6UrS8Kree3FhmP7>Cj_{FZ+v2GdcRI+HP5ZPzQhcfwD|j8!3PeF zC79VN6>cpMqhfmqZ&$Hah=|FSk!r9w)3Xd+XxjZ!CF+NeaEXZ4Z*Ojq+Hc=1T$&zd zRkw%0)Xpy5fyxxrS)>_5@cn^9ho0)(s^p8y5=8i6<T4M~0d4gV`>>N*ZfC+cMwLCX^xa&=} zqBR6MpRqN>A*A6dJ~yx|zS7+dBq&oeRd34xJ zG=I|!NfhO`RU8bDxqY)tjVct>rQ&BH=sta7GuQ0Yh!ok^NKHlZzyLQX7%KQlv2W_4 z`s@KM>JlEr=+9?n|PBNy}MuJF8!+^5hv{xdu!Hgr}L+Mjip zHPrmMC!(e?=c~M>F$~_*l{(JQ!8)^zVegLL6-U-?jB{XlHE~UZIe)jCB+Wql~9_kA!ZgwfsN6$ES=Q>GV{3 zOUK7xeU-)>Tly}})=_Z*9P?9QCj>lMj2hb(&0M$>JsNF!kSB4?&kzyYv@?Fg?0rPV z>m8kAEt{g4g66t+%AUI$=+-22rReZXuEB*2Ynk6OqH{f)6R)_0o(R2iM0UO7-NNH_ zqQNY?gPC>%%$1ctvZ&-;m;l+k3-3aEMTF5)F&ZQjN?8Nb)t*yS`uo#D;t8o#HrFl?vj|c%1oZA zK6Bf?sK6&Wo!z$EdC?=W&pw7n4js7O-s9qoEvbHK6%Z%wt0cHazTLOyF(3hCzvVUi zSx>xQt5|PCkzAz>Fn-xXIDr<)C(bA zVuX}!$LV-}A?67sJNr+@jj8!xvwk7XBZN~|g*ZuI20{b}lV=3S+?F6X93Ry10!uO~ ztQ_>{PtemuzaR5vs&J&dF<3LkW;Rl3gLHht6qH&Le)F5g^yc`@PZr4>CrH_Lmep7C z%zbKE(;H@KJ2vI++$+K8+urIq%!Y()p0gNPdN9EA#~0yFH(Gd?++^yDIG-KU}9@ zXIN)Efgb=YGu)o=3I=6kUVdkKx<%~_=miFbpsgt4&fmX!lb>??MJb-|UZ__H`C3TkEp@a{Ft?bZ+aZG5-d$OrS z!0h47WTSEudWI!jnsl(2?48VrmQmccX_$LDkZ2dfe9ZjeKDb%UPiUaISC{_Dh{=NW zz%0}OOp?Nq%x+J+j0EPVCJ~NS^1Y4DTbRpBL{b=5EhF4B^=my$i#*0f!iqLiT?SS` z`W@GBDuCvR4mh>`4sd$-BT0;ih>~5!)uPc}Sj81a21aH^)<*V5uFWgTDCh~bSwxjB z96SrzOP^nIHwZgZY}eonNp`BKK?U zu>QpHkH#)>K*>^Yzd;I#=iPi21yKSokC~|fWuMmLFzoDW`}d4@8xVG|&&gj%P3y&| z5-!rk2#0|{HP}9h@8!EF(qokxf_b6H z3$Qy}D(moa!TyxHEK?vbu%_%>ayE3pks~jbI}n2$d3TI&iD`gP|I(@oV9xs>M?qWk z%IeweomtyoCJqF(8IK=7KB?K1X>T6m0#J)Vt)y$w(K`~L<)qdi-6r^zy;6~Krq3nC zBFKv0yydn;0pTf7cI3_^fQhKO{u&?kK4Hm9P?WpIXqZCy`S|l$H>(R5#?6}E*b!TM zPP~-_a-Nsa2i?)r*O2xF>qES}9X$)KauMXP2YX|sJDfPSM7nJc^#saXS7;`Gk(6}u z6g9}WeT~k3@dVvYgvUSD9J#e7Sm$e{l?=j+0&t2en36kQUcg${UjD^X^ZtD==VxxiN}8@y=lXyd z%Mv4OO?^(XBT9J30VnWxvifts`xIaWRYG7R3g{THA;emz^JO93 zn>KGI9znWmNoteyqd<671&MgL;1Uyf<6GiW@6g^9zC>S!fQp70eyO1 z9nd8C%6a71RFPeGiXn!nhktxCy0>e{=Iih51X+F@D+2EioVGaR8`jvkDM&#_hS}$&jw5Z{f zn51CPxWX>mYkj^0CGUioO&VCgu^s+R%DBMRL~Uiwc3xk>mVLbVI#nr94jQ8nj+u!i z9}j^rgqctI#mr$sAdtqd{RS}dQgL&D(ujJ_yTKqF%?miBi`jF*10l0bZV!=35^2nK zN{%ZvEQFYIMIulk1D_vGP4yXbHgZ>n4F5lR1qj04n_Z|L;fs;b(Da~Xt7K%h8UUtI?U2oFTYLoNWIs}CtebxguHMRhG19Vqc zPV7mK0>7RvJ*63NvE!4+iBe>l-M5ZuAsa}j<+l9QED@=3>67tbD$?zSt$DM>RdqyY!Tiz8yD<4*Cb|OT|ulwC%P> ztBwaoy@-F+^zo}!!}THU)A41|tG+)z%l5-YSSIJAjP_J-@(ga`+5mGi4=wcxi+LZN z#br=oyEmBnWVGX|7Kx&@Z73^26Jtz*wo7r9QUZ-x-yk$5x(fUAhk9@<_n3H3TML*1TDu}5m`s~G$0ST|NjzJz_*)qn1@nNl49ZzLBQk*UQ(PEiov zv6&vFUImJbY!qIehO$se$If?EbpzrVS3g_3(^Ro3{e^z+rn_V;b z0f5!>?vXkFa`6TRF${wPuaGDAxlI@P$5xK=hPQ>X3+ey|e9>+YT}ZM5<3O)hco-G?0PXI$g6qN}A>S}R>{oRlY-P>eW#FZHy21&ODU}(AAVb%HR0iUR4)wWhfpadq+ zod7e!51DW`;TSLRV`a(uTJd1{scm;8NmWZl$*-@_OwD82LeU3{>S21fS_6BUMA_p# z1_-rFIr=M@#NgpIToON5IA*bFghHCI5rGQbWoL1KOyV~{V9lkp=p-3hCg)AZbIG{r z-J+Uang&!*$0tFbwGjAlqw;qo7MBN{xi=^u#1`MagV!n9c<4e%Y0y4mwNHFP!igzh z=pOLr;p$R1&@VIx0uLEM%+E}qH@_^0b98is&Ls8fucV%Q>g^NGu$ktNzui9w4E^>i zZ-XfsgXt`Kk!nieh$)by%&YSQFv8ZxCZ|g{73Ier9AL69p9?)3>jug&&zt*cRFOHN z-jb^zc@Om^!%Kd<5Ps>*{hhDOPJzeceT;mq56bw@OSV?+1>&pr2ABbnjPNGZ=%OJ+ zR-Z+g;^SPl1iGXZRzg-l`Kc1Tzi{+eV$y2p+Uc=|K}?9Lsy55jy7&Xa8GGVo+e5Yu zkqE{+==7h;rXUtPDv`cGQpRrSekvR`1u6-TLblFV3BHj0m#MP_!*U{2BCQ&;eOHb5 zwyCkvu88UBX+uff2#j?K84AAq#zqbBY^1 zQrWl3S6_z>7bJUVjJ(j;NLL|7bBj1n&`*=Xq^{lJ_*<(ti++1@(E2j{TENmp=YU`M zlY3vy)C*=m?C{hxG~0ab%Rrdj@1ME|G?jCC zF!$B~==LB8X)A}Sv@M+M%-U#fx8HKETk0RA6K{j{RYK5rfHyI;H*?Mw)P zE_#xz5rqnv7S~T1p>G9}u@Y|R-ciH{(}LL)_KNm9#_nUa%-o8R;Ww|XT>A^f>9Rsi z?Y_?FsZ@(fbS=1;maY>6{r096=+*ZLIAFCv0K-9EAKtxh3PfGaV(g7Qx#Q92L~N8q z-qxRbF^LHbCQ}ACG5>l|LWktXRnL)>2XaAymL}_XK?5 znd~z@982F}g+)5%gEn2`buZZo5?FA$z5Sbn895n+aW_XzFV%a>M);}46=5-kdw;vR3We-q!Ea0jt7oZ^}oz%I^w@^Bjw^ci6JM z)_3~uu$KAP7pLY^uIzG38kvNyx|e(7%Qq|&7*2J13B;@PHiSLdnvZ8$Osg-J4hYX# z!73~6?NT9_K?^Sj!xP84av;q^hPH&3m97=*)%SoXr4cxd&~j4EXW(mX65l=5nT_u^Tt*Hfj>7~^^xRQ zvMSR5q8@rgW@4GTQtTlJ5kY?&b)-Wowb~0mgy!F^TwyuJ6IMBNr8Cs20jT(A*tgZ# z?LyjTcn44=R2V;5I5;nZXxt3(XI#hmg06E>I>|dKEJly+%$e><5Op5@DRU@N+xbG? z)OjQh>rKioOJ?%-d{qogHy0*aJv}`{XI5-zJGxx*V3mP6r@;IeuDqaMjBVMXLz?CR zdw50!haSMnV3(ENin!F&7Va4T_4FblkM^D7oi_Ea&Sh3-Jx)l{sg6rX7;(&cEZMnx zVd&JR_afy|W?+Lx#yIxqpM~P?$jsD51n~`67R0j~d0qb}Fk6|PM2vTsz^k%66XAmn z+Jv&>s4ycy%}0nySTEnhJqEv0oZsSkUf#UdEZO}#5K44W*C;qzmlNx=2eo1y2*a&& z`-2TNE~#j1*UCRdw2aBVoeND+q3$T_P0D%x{CVAFbmvj_)QECTRp|icO&V5Xh4ZVdikF(AKZ5c2Vp6#C$pYkO<^}@uXV2w#09z3_ z`mtzEsinsg8w;Kh+T}Fo22`OyLF{5Q%?hnv(uXZ-lCtBx3+S!1jcr6H7!~$88`75Cw2l5e|l3v;D2}iCh4<9c4=Tjm^8M zfltrDbD!&go{W|gKovcD&ZSqMJAmYn6`d9jl-BjTv)S8q3=U{dL&l(!L<<}~bD#zf zkry;@JUes32&!e^%?*x_C~%fIE4Y(*E`ajyM-GS2!<$q^iY%UKEZSl%VV=oh_4Tf- zs(W4=QumXx0Uv!f=5+(x`i$*p^ea-DVyHW7my#BM$5yPX$c@6knpM=7pMl8vt7c{~ zR;s$8!AgD3B0(xZfJ@q?Cbj>9P4Qro8$zNF?Dd*Fo1T8W@0nMo$+OF^=T~5FQ&MN# z>W=P^*(}H+Q7k{idr#@kQP%9zbJ#Ve}Tu4y70?zS4rxH@EM_YFIej_xA(Ff$=4KfL5@2Lh_9e-M=U?b@wD_GS` z?{WJ^X*&+9ng9d>se`T@>TAxfa|kg>at}!8d(Sifl1u7pMa|=3NY`G;mQ?N7#=y8W zyeJ>0u>qgtPGDfPvIZp>jpedV7(NB9r@ya?)oQ9e@%pNzs^oV+Au(~xRx+^vy?E!f zx(F95)j5fY3z;w~L6j1R@Cx^#5T)Ve;qr>G~qCZsT=hT~o(drWX={%yL?!cf z_E69igRsoZN*5l4mH#OH$0ZhvbO~h;BLAw|vM@n%op$Nf@ua;7jZbK}}69|viloMKs zS>y66*xbzkse&ig5EX659K3r5A>|Cta=j*dSTdeFEoxfk8i{X=YTj#M-Do;5j6F9y!tuaFT-7_=*sFLV*JMk5y{Kz)Ne zqe}l4u}ip9nW?}?*qTHR9YSjpbUTadY0exYe}U!VLh@~6^-+^`APYQHu+A;FvM{D;lOzo#>!5ke5jh9y6A+hY%ubwI!5&nx_wl1 zbb$MA6mK~6uY3uM4sb^zp1Y_k*i_;$iCc05%@)br$iik>)X&7}X@4mdt)7 zf(1Qlkrv7?76ZOEVw6F*%n#`Ulcghc8YKFvxbvX4oub^FIP8($!OE(2rx@$z!?e~??TEkYf-a;AATcniACD@balpK9%2KE10%#`_iS7P6$Gr2X z_fki|Aa4x%_2-*icj+9dk48O(IQT#bDV&5B1pX<6is+zXTk0N`~Y$vK#GYc zlVT#@7hZ!7`pakm4G(_fQiFxt2Wc105?#L(KH-O`QEJkCabbrzOm8m!MfpvQ74?2o zg(j=WS=PVa6Mlg@;9*Cgphux&N<>$@81cV#jhzdDJ^36Ek>t67eaOq}ne_R6;#_?7 z!DL_>hbYI=Wb9qfGCvo2bm2(U0dRKs;Ea}ka;c`(V394Nq{Ec;adP5^njIdw57>vj z26y@i$}Y=m3-~C|C){*U(&mMiSvUm`?6t+RlEnUVug3_h8VVamOF0s@WnjxT|Ya}%w} z?@xCB{{DWvCm|Uc!$u@JbRos5Gy8e%aJLp=1;dZs1xr0s8MMzl&oi;Iv+xqRlo#@uPae>p->N<;tkDXXjXZ0;4}BtHu~!J zwA3tB4!|ZPS}d;IrRbydT*8O*+4r%)bIB0Gwb^_i2a5T-S^>N>up;LbD%#4nTpjRd++!R0?0)&d4#R&O=GEdOgZgL4sgvF=3`sd1piF|h|R;J zToAEBWIlK3~rB%6Oa| zM!2U6Dfc-fON%TGK4CDi=|?zw$|#qTuh3bcA}3bKnp#|jv=vVwBRL@%_XOpnl?O>m zX0OZ8N04Q8+z}wjIVwBMlp)uUDXK;3#iv-Zhgj1p(lhR3g>ETEjt2sio1jCz7sU1c z`S`r7p7iGzGhS-P5V5MNHQf#Whznr|Vn*~eb*)Ih{i)jEO_sYL@9*C!6IZaeNi98b zq+@qGpH76v5Sq zJ;X~r0BkyNbmqP2(^FIRpp_r;uP-zauK^ikTxYK(R9x)=kb5p!4=JalvZnwbM>|^~ zWKs^s1J?nP;BL9|MKLXd1+%PJkY*b4!-T=34rND|Fd?s)zC?vA2~Z1!nfQauDZ=pO z?EbG!O*RljWbxv_Q;^P^fRw2N=G{>6_eN4o?xFWHp9&bCY0kCW0`&JOb2Ae&b{4yl zK2sn!H|ajpAB*HnS^2H#8JAoNRvr5iZUyaT$Ek0(N?8BTWp`Px7G473icRU0gWxH3 zCP2g$JPZu@RRTD3NQ$IGZn+vGZnVNaDR0^eyoe_Uq4!QS%QYMNXKf*O1hX-+9xJwg zgP#2hTjGh+4GM3MHVh_m1q521Y57wqK#T~7gZ_b5>`UyNe;g!S2s&sp>Iy^$u4A>j z;66Hs9so{+-)(XT6-9X+@fF0$kkzpTA9B1zq&&#$lH2K`#@6}%)&^iN&szOWJpf_3 zr=*ke*GO*nZHMey^!Nxf)-aL|)=7RUH;t|K^y2VolE_jDf1DaftnUBlBUO|T5u>I{ zZa*!!zKYETfZDkykNdT2nEImJ5DZ1{E~cVEVA{9&{BXMmdsxz287^&`?y4wc{4(gy zh@88&P-k@yx1rEFM3)-0N(59 zrvHzkU;X8>Q_w~rJ@kPM$q6!-Rbr%yOFWN0zDJA<4?|KyvQ-J0nc~F*6IWszx}Azb zNKaXjO&7IvJ6K)eanE?(3Fd`CBjJqHdm$fU$R>j?+g%-F!WsfCNzmc_R z5M#-o%CvRr|B0y=*hSCy$40=l3;BdAV7^oEKYTQ$PTdY5h`Q9my6Pys7-Y2%q6cD6 zp)0#8PgU}zr>^(&^1wO(f=4={7sC52UOL5dkS2*X4F~Jl{o5;2<`6jKs?uZrajUh} zo}maxU1;;IVIsR{L>pI!yi%uw?ap0hf7}i$GyM)oo5I{FoGQIB_U4i}6lcdQ?1JnO zVSoXPf9=?-^Hkb3T|Ce|^0AjQq_@sOwVWug{-|vGFxqn4c3hFWVx!rZYsSHQVW8OrHDsA_J#>2W-lslH)%` zzk}Lg_Fe!yuuDBvqLi&0HNw+KhHQXNA|pG9R&dJ#6C$=A4>l_8Mx}|>I{w_zgrFy1(7^rkxO-+eHqZzKOC=}e|v4E zyR4Psl)65Q3Ue&Ii!9}`dJT20Rv?ZIuNBd0jr8BSsCCRx6n(!x*hdx8y%1SFFf=_0 zwn|o11VL|wozvD1SX0@2M`SK`6IAri>Q5=MLlxDf0jgU$q{;=D5YKzd{Y5|z|00zn)OI1+oZ^7<pn zb3*;3q#FuiSMhV254PkYJR>|;iMUXJRMo?<>^WuWU3G1MR!j7?l;;7Kz?0v2=D+ha z1n3%Df~Fjilg11LOF6$vj>*WMyqjO~5dqU>P!p55JIun=9!c2F2q@RZbnV@^0x8TY znBdnfx(vLmE9pBGJT_4AYXwtHoigU2S~3-F08{XO$B8FDd0sn$PbXUdSi1b$6b*0~ zj3CE-Wuz3^KE@#C^>TGcO6JV#-jZ1H`b;5)=QrE=AtbOP)v_1Y8u?8@6+*_!*FtH} zf`yhTwcrIO67`4*~(X-LB6%i3}E`}eqswKX+AS4Jw@30zh5>!>Q0 zDfZzm9J|IdTM)s^)6p3N?ITDj>O^M;u+}W9ANb8DhfbPwwnr6XbMsbEa{;_vs^_S) zwn&PF97X&PB9XW=8by*w+zpVf*!NoM#v2A6UFuqpzMtz^HIMLOhCe&X8gyggsc+SB zze;rQ-iN=}KP5w26gHLr9?hI4Z zB^+&eV5+A^c!c%rObdnaN6pJpNiQjD;FTyx9cRa6k>U^7t{#EEv0eX0R9oQCTF;*| zYOzOplQkq;GF!$bcT1l?E;wO<<_UnYVK?jMnvwhC&W^%`@xR$whikcqa=DN@_BChA z6}UR$Ta#R6>Tcs8v+i{!jILeLl!2j(ik~HIyMi1}Zo}uZ@2Y^-KYn*c%E189({9>9 z@vkipzu8{Tz%qRSaAD?d@xv331_YZ;vdSIu>xJ{M_lX5hZ{EDg?1GGO5^&suwDBPv z7W->qFp<9&af^ntG%T27r~TJmK>^c2-hntkONwl)G6sE8ijP z)a2#8uB|t+|4MJ%Cr|kn9tO4KlOs+REYel{v*<i$xQ?=FnP{PN`R*HQWzPb{?bdQG) zhfkt|=$Gjj265(iL*pphlaYa`X$yF(%&V27a|vvMYjTq%T^cBZlE(pWmC(fHJrLz=Hhw|A?n_6(+v3mG>6EK>h&# zeQ5%fyg7gFF9;#_4HB?=5WLN<`YfB2LefNwD@|EDJNe# zMtJ9cFXtkBf%bKbf(28Hl0*4zso+A@^fla~bfX%H%RtQ#<+B_Of_&9q_eppNnUnO12eM|9%pa_8LgA^`Wj_MHK+ZYk2jThpaHudZeF@&A?m9*b)C($C zm}PPBZMYbk^AAW3a^ja}px*;!VEHBHYEt$c89@1GT=?e)NQ>hRd^<7aT3ScLD;PL| zYwdrWVE7Km8O@^ihCm)*Nx7N&Ia+MB_^h-CBj~}2Wb6I%<>!(I|Cb69St6*;toIRE zj2~}KQlyD+nBCNndNtDBAU~FGFem}O-LM!;*Q&WtOvms`Vn50!{xuUXtVZ~;s%v8x zi}-So46;k)sWi0fEmL}i$adXbufFU=E(7vV@0W_xhL1-f1Gxl@Y=2R$;S_3VWq;WP zXnP_LQKPE5u_z-Dmk@Wt1Jd51{Px#6!0QEFaE?XR&yP~!>5HHG*JU7mM*$O}sSj6B zs)*DFci4&hzqCMw33!{+f(kT+W;%-I{1-#DRBW02krdZj4YdGliGi=^$s#W4#bqh^*bCv|PSPr;SW+NJZktN+2;LbE0%!x2 z_J`tycQC+8rYvzW{{7^VcZMYaC&w_#(#vA`H_RS$7%%rX zRJGoe+?a$0JElr+vgIZXqJ|BmBQDooh!8J}1_=+~n3`|%?Kof|XM(^G&z5z@c|1TeagM=L2Y-DX+IsQc6cx&R-|MOTZ$zM~qqM#5>oT4){cs!^La-1FG*6W!KEzab_g+5 z@3hjX@DMcCnbJ~>e=YRV`-f&jNN7(fYmkY`X#e})y9J(rYBaBWSRh<}Fz-@@@U0FAG=^RmpJs0OE|X#L(F;y&~z_OLX1h zmrcRZ{AvBcJS=$W!~XaGllJ^E0_)xG@;#VZWFUR^|Mp!7XOPqUEt$8S7ELM~#>@N< zbpSIwAbJZr{uYM_`Q$2LS}!;4OfIpw)MLu&0^0Fri~oj|I}7R;pOy049}7p>7vzXu zL$n*~)sR1o9}RN@>a~-x5w#S~F5HA7gN%9Ml94zXCJH8PP+b_)AatH%c{7=2t1kn; zggb>)7Qy8(1g)l?Emjfuo-1W6qyRVzPwx_Z0SMvO$+=aa4ZygJB zUv$P==WlJ7$@th;K3}{)YznpNn%A3^4zfEQ5rEHf`}$SPs2ig}8`Vj3ca|+TC=Diz zqp1%wVJp`3(;w>;wS$}xRr)(2dZtUwq3)ooZ1mh*+>Dl-G;}9251K5tl+q-rd6kcg z@#I32qB{!Fa@Ka zOn^_Ae31=#AzxaGzVC(np4wRy3oU>UFSND%5faCbTK9$dePBi|ao`KQny>1Z-;?K9wsGnF8S?h?s}R6h#QwUzjP{(o z{|J?~kqSZ(NgaB+{?4W2@1EaBa*g{T*O)-dHBvR&Am$}Bo!;2NifzCz5A;9a@Fe`m z_8n~@U(jRxrd~hY@N8>tbi#O2^XZ{CXBwnIc(# zX);5kzvk{{b#O~C2KdS)iB9rO{`CRmi?(l9ivTs|=o?HT6QJk;(sj4*Dj+A~m!20= vat?A=vkP=|bPEe69P`HT3nSu4tf2coTbDhaHg5p0&?(8EJeqXa)a(BPat5s$ literal 104455 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 Date: Sun, 29 Mar 2026 22:44:13 +0900 Subject: [PATCH 82/82] =?UTF-8?q?refactor:=20=EB=84=A4=EC=9D=B4=EB=B0=8D?= =?UTF-8?q?=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/BoardInitializer.java | 27 ++++ src/main/java/GameRunner.java | 147 ++++++++++++++++++ src/test/java/BoardInitializerTest.java | 92 +++++++++++ .../java/strategy/move/MoveStrategyTest.java | 10 ++ 4 files changed, 276 insertions(+) create mode 100644 src/main/java/BoardInitializer.java create mode 100644 src/main/java/GameRunner.java create mode 100644 src/test/java/BoardInitializerTest.java create mode 100644 src/test/java/strategy/move/MoveStrategyTest.java diff --git a/src/main/java/BoardInitializer.java b/src/main/java/BoardInitializer.java new file mode 100644 index 0000000000..f7ad6b0204 --- /dev/null +++ b/src/main/java/BoardInitializer.java @@ -0,0 +1,27 @@ +import domain.board.Board; +import domain.piece.Piece; +import domain.board.Position; +import domain.piece.TeamColor; +import java.util.HashMap; +import java.util.Map; +import strategy.formation.InitialFormationStrategy; + +public class BoardInitializer { + + private final InitialFormationStrategy choStrategy; + private final InitialFormationStrategy hanStrategy; + + public BoardInitializer(InitialFormationStrategy choStrategy, InitialFormationStrategy hanStrategy) { + this.choStrategy = choStrategy; + this.hanStrategy = hanStrategy; + } + + public Board initialize() { + final Map board = new HashMap<>(); + board.putAll(choStrategy.createInitialPieces(TeamColor.CHO)); + board.putAll(hanStrategy.createInitialPieces(TeamColor.HAN)); + return new Board(board); + } +} + + diff --git a/src/main/java/GameRunner.java b/src/main/java/GameRunner.java new file mode 100644 index 0000000000..affd22e5fc --- /dev/null +++ b/src/main/java/GameRunner.java @@ -0,0 +1,147 @@ +import domain.board.Board; +import domain.piece.Piece; +import domain.board.Position; +import domain.board.Route; +import domain.piece.TeamColor; +import domain.game.TurnManager; +import io.InputView; +import io.OutputView; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import strategy.formation.InitialFormationStrategy; +import strategy.formation.InnerFormationStrategy; +import strategy.formation.LeftFormationStrategy; +import strategy.formation.OuterFormationStrategy; +import strategy.formation.RightFormationStrategy; + +public class GameRunner { + private static final int FIRST_OPTION_NUMBER = 1; + private static final int BACK_OPTION_NUMBER = 0; + private static final int ZERO_BASE_INDEX_OFFSET = 1; + private static final List FORMATIONS = List.of( + new InnerFormationStrategy(), + new OuterFormationStrategy(), + new LeftFormationStrategy(), + new RightFormationStrategy() + ); + + private final InputView inputView; + private final OutputView outputView; + private final TurnManager turnManager; + + public GameRunner() { + this(new InputView(), new OutputView(), new TurnManager()); + } + + public GameRunner(InputView inputView, OutputView outputView, TurnManager turnManager) { + this.inputView = inputView; + this.outputView = outputView; + this.turnManager = turnManager; + } + + public void run() { + outputView.printGameStart(); + + InitialFormationStrategy choStrategy = chooseFormationStrategy(TeamColor.CHO); + InitialFormationStrategy hanStrategy = chooseFormationStrategy(TeamColor.HAN); + + BoardInitializer boardInitializer = new BoardInitializer(choStrategy, hanStrategy); + Board board = boardInitializer.initialize(); + + outputView.printBoard(board); + + while (true) { + playTurn(board); + } + } + + private InitialFormationStrategy chooseFormationStrategy(TeamColor teamColor) { + while (true) { + outputView.printFormationSelectionPrompt(teamColor); + try { + return createFormationStrategy(inputView.readFormationChoice(teamColor)); + } catch (RuntimeException exception) { + outputView.printError("상차림 입력이 올바르지 않습니다."); + } + } + } + + private void playTurn(Board board) { + final TeamColor currentTurn = turnManager.getCurrentTurn(); + outputView.printCurrentTurn(currentTurn); + outputView.printBoard(board); + + while (true) { + try { + final Piece selectedPiece = choosePiece(board, currentTurn); + final Optional selectedRoute = chooseRoute(board, selectedPiece); + if (selectedRoute.isEmpty()) { + continue; + } + + final Position destination = selectedRoute.get().endPos(); + board.move(selectedPiece, destination); + outputView.printMoveResult(selectedPiece, destination); + turnManager.advanceTurn(); + return; + } catch (RuntimeException exception) { + outputView.printError(exception.getMessage()); + } + } + } + + private InitialFormationStrategy createFormationStrategy(int choice) { + validateFormationChoice(choice); + return FORMATIONS.get(choice - ZERO_BASE_INDEX_OFFSET); + } + + private void validateFormationChoice(int choice) { + if (choice >= FIRST_OPTION_NUMBER && choice <= FORMATIONS.size()) { + return; + } + throw new IllegalArgumentException("상차림 번호는 1~4 사이여야 합니다."); + } + + private Piece choosePiece(Board board, TeamColor currentTurn) { + List> pieces = board.findPiecesByTeam(currentTurn); + outputView.printPieceOptions(pieces); + + final int pieceChoice = inputView.readPieceChoice(currentTurn); + return getSelectedPiece(pieces, pieceChoice); + } + + private Optional chooseRoute(Board board, Piece selectedPiece) { + final List routes = board.findMovableRoutes(selectedPiece); + validateMovableRoutes(routes); + outputView.printRouteOptions(routes); + + final int routeChoice = inputView.readRouteChoice(); + if (routeChoice == BACK_OPTION_NUMBER) { + return Optional.empty(); + } + return Optional.of(getSelectedRoute(routes, routeChoice)); + } + + private void validateMovableRoutes(List routes) { + if (routes.isEmpty()) { + throw new IllegalArgumentException("선택한 기물은 이동 가능한 경로가 없습니다."); + } + } + + private Piece getSelectedPiece(List> pieces, int pieceChoice) { + if (pieceChoice < FIRST_OPTION_NUMBER || pieceChoice > pieces.size()) { + throw new IllegalArgumentException("기물 번호가 범위를 벗어났습니다."); + } + return pieces.get(pieceChoice - ZERO_BASE_INDEX_OFFSET).getValue(); + } + + private Route getSelectedRoute(List routes, int routeChoice) { + if (routeChoice < FIRST_OPTION_NUMBER || routeChoice > routes.size()) { + throw new IllegalArgumentException("경로 번호가 범위를 벗어났습니다."); + } + return routes.get(routeChoice - ZERO_BASE_INDEX_OFFSET); + } +} + + diff --git a/src/test/java/BoardInitializerTest.java b/src/test/java/BoardInitializerTest.java new file mode 100644 index 0000000000..6e3d4a00dc --- /dev/null +++ b/src/test/java/BoardInitializerTest.java @@ -0,0 +1,92 @@ +import domain.board.Board; +import domain.piece.PieceType; +import domain.board.Position; + +import domain.piece.TeamColor; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + + + +import static org.assertj.core.api.Assertions.assertThat; +import strategy.formation.InitialFormationStrategy; +import strategy.formation.InnerFormationStrategy; + +class BoardInitializerTest { + + InitialFormationStrategy choStrategy; + InitialFormationStrategy hanStrategy; + Board board; + + @BeforeEach + public void setUp(){ + choStrategy = new InnerFormationStrategy(); + hanStrategy = new InnerFormationStrategy(); + BoardInitializer boardInitializer = new BoardInitializer(choStrategy, hanStrategy); + board = boardInitializer.initialize(); + } + + + @Nested + class 초기화 { + @Test + void 초나라_한나라_전략을_주입받아_총_32개의_기물이_세팅된_초기_장기판을_반환한다() { + assertThat(board.findPiecesByTeam(TeamColor.CHO)).hasSize(16); + assertThat(board.findPiecesByTeam(TeamColor.HAN)).hasSize(16); + assertThat(board.findPiece(Position.of(8, 4))).get().extracting("pieceType").isEqualTo(PieceType.KING); + assertThat(board.findPiece(Position.of(0, 2))).get().extracting("pieceType").isEqualTo(PieceType.ELEPHANT); + } + } + + @Nested + class 기물목록 { + @Test + void 초나라_기물_리스트를_생성한다() { + assertThat(board.findPiecesByTeam(TeamColor.CHO)).hasSize(16); + assertThat( + board.findPiecesByTeam(TeamColor.CHO).stream() + .map(entry -> entry.getValue()) + .filter(p -> p.getPieceType() == PieceType.ELEPHANT) + ).hasSize(2); + + assertThat( + board.findPiecesByTeam(TeamColor.CHO).stream() + .map(entry -> entry.getValue()) + .filter(p -> p.getPieceType() == PieceType.HORSE) + ).hasSize(2); + + assertThat( + board.findPiecesByTeam(TeamColor.CHO).stream() + .map(entry -> entry.getValue()) + .filter(p -> p.getPieceType() == PieceType.CANNON) + ).hasSize(2); + + assertThat( + board.findPiecesByTeam(TeamColor.CHO).stream() + .map(entry -> entry.getValue()) + .filter(p -> p.getPieceType() == PieceType.ROOK) + ).hasSize(2); + + assertThat( + board.findPiecesByTeam(TeamColor.CHO).stream() + .map(entry -> entry.getValue()) + .filter(p -> p.getPieceType() == PieceType.GUARD) + ).hasSize(2); + + assertThat( + board.findPiecesByTeam(TeamColor.CHO).stream() + .map(entry -> entry.getValue()) + .filter(p -> p.getPieceType() == PieceType.PAWN) + ).hasSize(5); + + assertThat( + board.findPiecesByTeam(TeamColor.CHO).stream() + .map(entry -> entry.getValue()) + .filter(p -> p.getPieceType() == PieceType.KING) + ).hasSize(1); + } + } +} + + diff --git a/src/test/java/strategy/move/MoveStrategyTest.java b/src/test/java/strategy/move/MoveStrategyTest.java new file mode 100644 index 0000000000..d949eaee4d --- /dev/null +++ b/src/test/java/strategy/move/MoveStrategyTest.java @@ -0,0 +1,10 @@ +package strategy.move; + +import org.junit.jupiter.api.Test; + +public class MoveStrategyTest { + + +} + +