Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[4, 5단계 - 체스] 기론(김규철) 미션 제출합니다. #357

Merged
merged 41 commits into from
Apr 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
335590b
refactor: 에러 출력을 담당하는 exception class 추가
Gyuchool Apr 1, 2022
05c4241
feat: 초기 체스판 세팅
Gyuchool Apr 2, 2022
90c0077
feat: post /move 로 움직이는 기능 구현
Gyuchool Apr 3, 2022
734d65d
refactor: dto변환 위치 변경
Gyuchool Apr 3, 2022
66afd19
refactor: html. css, js 수정
Gyuchool Apr 3, 2022
f2bf52e
feat: status api 기능 구현
Gyuchool Apr 3, 2022
18924f2
test: jdbc connection 테스트 추가
Gyuchool Apr 3, 2022
35cc84b
refactor: piece 테스트 수정
Gyuchool Apr 3, 2022
4d5594e
refactor: api 네이밍 변경
Gyuchool Apr 3, 2022
e69f383
test: boardDao test추가
Gyuchool Apr 4, 2022
f0cc4ec
test: pieceDao test 추가
Gyuchool Apr 4, 2022
04e8c0a
test: ChessServiceTest 추가
Gyuchool Apr 4, 2022
78409f9
docs: readme에 api명세 추가
Gyuchool Apr 5, 2022
4ee3400
refactor: chessServiceTest mock 객체를 사용해서 테스트하도록 수정
Gyuchool Apr 5, 2022
9cdda01
refactor: dto변환 로직 dto내에서 수행하도록 수정
Gyuchool Apr 6, 2022
98daf05
refactor: 적절한 예외메시지가 나오도록 수정
Gyuchool Apr 6, 2022
4c31338
fix: restart 이후 기물이 움직이도록 수정
Gyuchool Apr 6, 2022
38c36ec
refactor: restart 이후 start버튼만 나오던 UI 수정
Gyuchool Apr 6, 2022
516bdd1
refactor: gson 인스턴스를 정적으로 선언
Gyuchool Apr 6, 2022
8e37744
refactor: dto내부의 변수 이름 수정
Gyuchool Apr 6, 2022
7567805
refactor: 코드 포멧팅 및 의미없는 공백 제거
Gyuchool Apr 6, 2022
3e15f8b
refactor: test 수행 후, 테스트했던 db내용들 롤백하도록 수정
Gyuchool Apr 6, 2022
2a30411
refactor: 테스트 코드 명세 명확하도록 수정
Gyuchool Apr 6, 2022
62b6fea
refactor: Empty의 type과 team을 호출할 떄, PieceFactory에서 싱글톤으로 값을 갖고 있도록 구현
Gyuchool Apr 6, 2022
8fd34ae
refactor: 변수 네이밍 변경
Gyuchool Apr 6, 2022
bee6b51
refactor: 테스트 코드 가독성 추가
Gyuchool Apr 6, 2022
b8f2615
refactor: test코드 명세 수정
Gyuchool Apr 6, 2022
b5500cb
refactor: api 변경에 따른 js에서 scoreDto받는 네이밍 변경
Gyuchool Apr 6, 2022
0936db7
refactor: 테스트 네이밍 추상화있게 수정
Gyuchool Apr 7, 2022
cbe22f2
refactor: 주석 제거 및 변수네이밍 변경
Gyuchool Apr 7, 2022
df48432
refactor: js 비교문에 ===을 사용하도록 수정
Gyuchool Apr 7, 2022
64bcd98
refactor: api명세서 박스를 통해 가독성 증가시키도록 수정
Gyuchool Apr 7, 2022
eccf42b
docs: api명세서에 구분선 추가
Gyuchool Apr 7, 2022
580ce4c
refactor: team내부의 하드코딩 제거
Gyuchool Apr 7, 2022
31c0681
refactor: 함수형인터페이스 사용으로 조건문 제거
Gyuchool Apr 7, 2022
3534067
refactor: 사용하지 않는 이미지 제거
Gyuchool Apr 7, 2022
cdfc911
refactor: fakePiece -> mockPiece로 네이밍 수정
Gyuchool Apr 7, 2022
e87699e
refactor: empty생성을 통해 하드코딩 제거
Gyuchool Apr 7, 2022
bb0e2d7
fix: 테스트 수행 후, 게임 실행시킬때 정상적으로 초기화 되도록 수정
Gyuchool Apr 7, 2022
ba580e6
refactor: 사용하지 않는 코드 제거
Gyuchool Apr 7, 2022
4b62c8e
refactor: test 명세 추상적이도록 수정
Gyuchool Apr 7, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
103 changes: 103 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,106 @@
- [x] 남아있는 말에 대해서 점수를 계산한다.
- [x] 게임이 끝나고 `status`를 입력하면 결과를 보여주고 우승 팀을 알려준다.
- [x] 게임이 끝나고 아무키나 입력하면 그냥 종료된다.

## 4, 5단계

### api 명세

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API 명세를 보기 좋도록 table을 활용하여 표현해볼까요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

table을 사용하니 보기에 더 깔끔해졌네요 !

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨어요! 회사에 들어와보니 문서를 잘 작성하는 것도 능력이더라구요! 지금부터 조금씩 연습해보죠!
추가로 API 명세는 서버쪽에서 담당해야하는 책임이기에 읽기 좋게 만들어주면 협업할 때에 도움이 됩니다!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋은 말씀 감사합니다...진짜 최고에요 토니!
경험과 함께 말씀해주시니깐 완전 동기부여가 되네요😃
감사합니당


| METHOD | URL | description |
|:-------:|:---------------:|:--------------------------------------:|
| GET | / | `index.html`을 부르면서 처음 페이지를 불러옵니다. |
| GET | /api/load | 현재 진행 중인 게임을 불러옵니다. |
| GET | /api/restart | 게임을 재시작합니다. 체스판과 체스 기물들이 초기화되어서 생성됩니다. |

위 api들은 `boardDto`를 통해서 아래의 json형태로 보내줍니다.

### Response Body

| name | type |
|:----------:|:---------------------:|
| turn | String |
| board | Map<String, String> |
| isFinish | boolean |

```json
{
turn: "white",
board: {
"a2": "pawn",
...
(position: piece)
...
},
isFinish: true
}
```

***

| METHOD | URL | description |
|:------:|:-----------:|:-----------------:|
| GET | /api/status | 현재 게임의 점수를 보여줍니다. |

위 api는 아래의 json형태로 보내줍니다.

### Response Body

| name | type |
|:--------------:|:------:|
| blackTeamScore | double |
| whiteTeamScore | double |

```json
{
blackTeamScore: 38.0,
whiteTeamScore: 38.0
}

```

***

| METHOD | URL | description |
|:------:|:---------:|:-------------------------:|
| POST | /api/move | 체스 기물들을 from에서 to로 움직입니다. |

위 api는 아래와 같은 형태로 `from`위치와 `to`위치를 json형태로 보내주고 통신합니다.

### Request Body

| name | type |
|:----:|:------:|
| from | String |
| to | String |

```json
POST
{
"from": "a2",
"to": "a4"
}
```

### Response Body

| name | type |
| ------|------|
| turn | String |
| board | Map<String, String> |
| isFinish | boolean |

```json
{
turn: "white",
board: {
"a2": "pawn",
...
(position: piece)
...
},
isFinish: true
}
```



1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ dependencies {
implementation 'com.sparkjava:spark-core:2.9.3'
implementation 'com.sparkjava:spark-template-handlebars:2.7.1'
implementation 'ch.qos.logback:logback-classic:1.2.10'
implementation 'com.google.code.gson:gson:2.8.7'
runtimeOnly 'mysql:mysql-connector-java:8.0.28'
testImplementation 'org.assertj:assertj-core:3.22.0'
testImplementation 'org.junit.jupiter:junit-jupiter:5.8.2'
Expand Down
96 changes: 88 additions & 8 deletions docker/db/mysql/init/init.sql
Original file line number Diff line number Diff line change
@@ -1,15 +1,95 @@
CREATE TABLE member
DROP TABLE IF EXISTS board;
DROP TABLE IF EXISTS piece;

CREATE TABLE board
(
id varchar(10) not null,
name varchar(20) not null,
id INT(10) not null AUTO_INCREMENT ,
turn VARCHAR (5) not null,
primary key (id)
);

CREATE TABLE role
INSERT INTO board (turn) VALUES ("white");

CREATE TABLE piece
(
member_id varchar(10) not null,
role varchar(10) not null,
primary key (member_id),
foreign key (member_id) references member (id)
id INT(10) not null AUTO_INCREMENT,
board_id INT(10),
position CHAR(2),
type VARCHAR (20) not null,
team VARCHAR (10) not null,
foreign key (board_id) references board (id) ON DELETE CASCADE ,
primary key (id)
);

INSERT INTO piece (position, board_id, type, team) VALUES ("a1", 1, "rook", "white");
INSERT INTO piece (position, board_id, type, team) VALUES ("b1", 1, "knight", "white");
INSERT INTO piece (position, board_id, type, team) VALUES ("c1", 1, "bishop", "white");
INSERT INTO piece (position, board_id, type, team) VALUES ("d1", 1, "queen", "white");
INSERT INTO piece (position, board_id, type, team) VALUES ("e1", 1, "king", "white");
INSERT INTO piece (position, board_id, type, team) VALUES ("f1", 1, "bishop", "white");
INSERT INTO piece (position, board_id, type, team) VALUES ("g1", 1, "knight", "white");
INSERT INTO piece (position, board_id, type, team) VALUES ("h1", 1, "rook", "white");

INSERT INTO piece (position, board_id, type, team) VALUES ("a2", 1, "pawn", "white");
INSERT INTO piece (position, board_id, type, team) VALUES ("b2", 1, "pawn", "white");
INSERT INTO piece (position, board_id, type, team) VALUES ("c2", 1, "pawn", "white");
INSERT INTO piece (position, board_id, type, team) VALUES ("d2", 1, "pawn", "white");
INSERT INTO piece (position, board_id, type, team) VALUES ("e2", 1, "pawn", "white");
INSERT INTO piece (position, board_id, type, team) VALUES ("f2", 1, "pawn", "white");
INSERT INTO piece (position, board_id, type, team) VALUES ("g2", 1, "pawn", "white");
INSERT INTO piece (position, board_id, type, team) VALUES ("h2", 1, "pawn", "white");

INSERT INTO piece (position, board_id, type, team) VALUES ("a3", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("b3", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("c3", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("d3", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("e3", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("f3", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("g3", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("h3", 1, "empty", "none");

INSERT INTO piece (position, board_id, type, team) VALUES ("a4", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("b4", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("c4", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("d4", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("e4", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("f4", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("g4", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("h4", 1, "empty", "none");

INSERT INTO piece (position, board_id, type, team) VALUES ("a5", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("b5", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("c5", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("d5", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("e5", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("f5", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("g5", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("h5", 1, "empty", "none");

INSERT INTO piece (position, board_id, type, team) VALUES ("a6", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("b6", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("c6", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("d6", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("e6", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("f6", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("g6", 1, "empty", "none");
INSERT INTO piece (position, board_id, type, team) VALUES ("h6", 1, "empty", "none");

INSERT INTO piece (position, board_id, type, team) VALUES ("a7", 1, "pawn", "black");
INSERT INTO piece (position, board_id, type, team) VALUES ("b7", 1, "pawn", "black");
INSERT INTO piece (position, board_id, type, team) VALUES ("c7", 1, "pawn", "black");
INSERT INTO piece (position, board_id, type, team) VALUES ("d7", 1, "pawn", "black");
INSERT INTO piece (position, board_id, type, team) VALUES ("e7", 1, "pawn", "black");
INSERT INTO piece (position, board_id, type, team) VALUES ("f7", 1, "pawn", "black");
INSERT INTO piece (position, board_id, type, team) VALUES ("g7", 1, "pawn", "black");
INSERT INTO piece (position, board_id, type, team) VALUES ("h7", 1, "pawn", "black");

INSERT INTO piece (position, board_id, type, team) VALUES ("a8", 1, "rook", "black");
INSERT INTO piece (position, board_id, type, team) VALUES ("b8", 1, "knight", "black");
INSERT INTO piece (position, board_id, type, team) VALUES ("c8", 1, "bishop", "black");
INSERT INTO piece (position, board_id, type, team) VALUES ("d8", 1, "queen", "black");
INSERT INTO piece (position, board_id, type, team) VALUES ("e8", 1, "king", "black");
INSERT INTO piece (position, board_id, type, team) VALUES ("f8", 1, "bishop", "black");
INSERT INTO piece (position, board_id, type, team) VALUES ("g8", 1, "knight", "black");
INSERT INTO piece (position, board_id, type, team) VALUES ("h8", 1, "rook", "black");

2 changes: 1 addition & 1 deletion src/main/java/chess/ConsoleApplication.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package chess;

import chess.controller.ChessController;
import chess.console.controller.ChessController;

public class ConsoleApplication {
public static void main(String[] args) {
Expand Down
18 changes: 0 additions & 18 deletions src/main/java/chess/Team.java

This file was deleted.

22 changes: 8 additions & 14 deletions src/main/java/chess/WebApplication.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,16 @@
package chess;

import spark.ModelAndView;
import spark.template.handlebars.HandlebarsTemplateEngine;
import chess.web.controller.ChessWebController;
import chess.web.service.ChessService;

import java.util.HashMap;
import java.util.Map;

import static spark.Spark.get;
import static spark.Spark.port;
import static spark.Spark.staticFileLocation;

public class WebApplication {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

웹에서 한 게임을 완료한 후 정상적으로 게임을 재시작할 수 없네요 😂

관련 재현 영상은 용량이 큰 관계로 DM 으로 보내드릴게요!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

board를 초기화 하고 piece들도 초기화 해야하는데 기존의 piece들의 position을 수정하지 않고 새로운 초기화된 piece 64개를 만들어서 오류가 생겼었네요!

initBoard()로직을 기존의 piece들의 position을 초기화하는 방식으로 수정했습니다!

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

문제점을 파악하여 잘 수정해주셨네요! 좋습니다~!

public static void main(String[] args) {
get("/", (req, res) -> {
Map<String, Object> model = new HashMap<>();
return render(model, "index.html");
});
}

private static String render(Map<String, Object> model, String templatePath) {
return new HandlebarsTemplateEngine().render(new ModelAndView(model, templatePath));
port(8080);
staticFileLocation("static");
ChessWebController chessController = new ChessWebController(new ChessService());
chessController.run();
}
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,34 @@
package chess;
package chess.board;

import chess.piece.Empty;
import chess.piece.Piece;
import chess.piece.Pieces;
import chess.piece.position.Position;
import chess.board.piece.Empty;
import chess.board.piece.Piece;
import chess.board.piece.Pieces;
import chess.board.piece.position.Position;

import java.util.List;

public final class Board {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

콘솔에서 게임을 플레이할 때에 의도와 다른 예외 메시지가 발생해요.

white가 b2에서 b4로 이동한 후에 다음 자신의 턴에 다시 b2에서 b3로 이동하려할 때에 white의 차례임에도 불구하고 현재 차례가 아닙니다. 라는 메시지가 보여지네요!

image

도메인에 수정이 가해지며 콘솔 체스에도 영향이 간 모양이에요! 확인해볼까요~?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Team에서 none인 팀까지 자신의 팀이라고 생각되어서 적절한 메시지가 안 갔었네요!
team비교하는 로직을 수정해서 고쳤습니다!

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

확인했어요~!
리팩터링을 진행하며 기존 로직에 변화가 발생하여 이런 문제가 생겼죠?!
이런 상황을 방지하려면 테스트 코드를 꼼꼼하게 작성하면 좋을거에요.


private final Pieces pieces;
private final Turn turn;

private Board(Pieces pieces) {
private Board(Pieces pieces, Turn turn) {
this.pieces = pieces;
this.turn = turn;
}

public static Board create(Pieces pieces) {
return new Board(pieces);
public static Board create(Pieces pieces, Turn turn) {
return new Board(pieces, turn);
}

public Pieces getPieces() {
return pieces;
}

public Turn getTurn() {
return turn;
}

public void move(List<String> commandPosition, Turn thisTurn) {
Position sourcePosition = getSource(commandPosition);
Position targetPosition = getTarget(commandPosition);
Expand All @@ -35,7 +41,7 @@ public void move(List<String> commandPosition, Turn thisTurn) {
}

private void validateTurn(Turn thisTurn, Piece sourcePiece) {
if (!sourcePiece.isCurrentTurn(thisTurn)) {
if (sourcePiece.isNotCurrentTurn(thisTurn)) {
throw new IllegalArgumentException("[ERROR] 현재 차례가 아닙니다.");
}
}
Expand Down
35 changes: 35 additions & 0 deletions src/main/java/chess/board/Team.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package chess.board;

import java.util.Arrays;

public enum Team {
BLACK(-1),
WHITE(1),
NONE(0),
;

private final int forwardDirection;

Team(int forwardDirection) {
this.forwardDirection = forwardDirection;
}

public static Team from(String name) {
return Arrays.stream(values())
.filter(team -> team.value().equals(name))
.findFirst()
.orElse(Team.NONE);
}

public String value() {
return this.name().toLowerCase();
}

public boolean isOpposingTeam(Team team) {
return this.forwardDirection + team.forwardDirection == 0;
}

public int getForwardDirection() {
return this.forwardDirection;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package chess;
package chess.board;

import java.util.Objects;

Expand All @@ -13,8 +13,8 @@ public static Turn init() {
return new Turn(Team.WHITE);
}

public boolean isCurrentTeam(Team team) {
return this.team.equals(team);
public boolean isNotCurrentTurn(Team team) {
return this.team.isOpposingTeam(team);
}

public Turn change() {
Expand All @@ -24,6 +24,10 @@ public Turn change() {
return new Turn(Team.BLACK);
}

public Team getTeam() {
return team;
}

@Override
public boolean equals(Object o) {
if (this == o) {
Expand Down