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

[라빈] 체스 웹/DB 미션 제출합니다 #133

Merged
merged 82 commits into from
Apr 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
67ceea2
doc: 체스 1단계 기능 요구 사항 정리
giantim Mar 24, 2020
eee6977
feat: 위치 구현
giantim Mar 24, 2020
a49d949
feat: 가로 축 구현
giantim Mar 24, 2020
16267b5
feat: 보드판 초기화
giantim Mar 25, 2020
9d82c72
feat: 체스 게임을 시작하는 명령어 입력
giantim Mar 25, 2020
3dcf3f9
feat: 이동 전략 구현
Mar 25, 2020
b0392f3
feat: 폰의 이동 전략과 팀별 이동 전략
giantim Mar 25, 2020
08ab69b
feat: 말 이동 시 장애물 탐색
giantim Mar 26, 2020
1d69dbf
feat: 방향 전략 구현
Mar 26, 2020
c6fd4f6
feat: 2단계 구현
giantim Mar 26, 2020
b757656
feat: 왕이 죽었을 때 승리한 팀 출력
giantim Mar 26, 2020
202d590
feat: 왕이 죽었을 때 게임 종료
giantim Mar 26, 2020
622ee0a
feat: status 명령어 입력 시 점수 계산
Mar 26, 2020
6a94761
feat: 3단계 기능 구현
giantim Mar 26, 2020
fdc9cfa
doc: README 업데이트
giantim Mar 26, 2020
fb4d0af
refactor: 세부 네이밍 수정
Mar 26, 2020
236e066
refactor: 방향 전략 생성 분기문 삭제
Mar 27, 2020
bf61f63
refactor: 테스트 코드 디렉토리 추가
giantim Mar 27, 2020
9d29cfd
refactor: 테스트 코드 추가
giantim Mar 27, 2020
db9009f
refactor: 변경되면 안되는 매개 변수, 클래스에 final 키워드 추가
giantim Mar 28, 2020
fd4d688
refactor: 컨트롤러의 실행 메서드를 명령어 별로 분리
giantim Mar 28, 2020
6f15464
refactor: DirectionStrategy 의 구현 클래스들의 테스트 코드 추가
giantim Mar 28, 2020
31e70ae
refactor: 컨트롤러 추상화
giantim Mar 30, 2020
a1f1431
refactor: 컨트롤러 추상화(2)
giantim Mar 31, 2020
7bd04ff
refactor: 1차 수정
giantim Mar 31, 2020
8888b08
refactor: Dto 추가 / ChessRunner 에서 Dto 에 적합한 값을 넘겨주도록 메서드 수정
giantim Mar 31, 2020
08cbd73
refactor: 게임 종료 경우에 따라 점수 출력 로직 구현 / 객체 null 반환을 Optional 을 이용하도록 변경 …
giantim Mar 31, 2020
12de745
Merge branch 'mission1' into home
giantim Apr 1, 2020
a6b5b67
Merge pull request #1 from giantim/home
giantim Apr 1, 2020
bdf1a0a
refactor: 수정한 클래스에 맞게 테스트 코드 추가
giantim Apr 1, 2020
74a6cd1
feat: index 페이지 제작
giantim Apr 1, 2020
3fcd39d
feat: index 에서 start 를 누르면 game 으로 이동되도록 구현
giantim Apr 1, 2020
96bfcc5
feat: 체스판에 말 띄우기
giantim Apr 1, 2020
46d168e
feat: 보드 위에 말 출력
giantim Apr 2, 2020
89f7a6a
feat: 웹에서 상태 출력 / 종료 기능 구현
giantim Apr 2, 2020
9f2711e
refactor: 이동을 못하는 버그 수정
giantim Apr 3, 2020
02de889
Merge pull request #2 from giantim/mission1
giantim Apr 3, 2020
28cbe8d
refactor: 웹에서 이동 기능 구현
giantim Apr 3, 2020
e0628cb
refactor: 에러 로그, 이동 경로 출력 버그 수정
giantim Apr 4, 2020
f33689e
Merge pull request #3 from giantim/web
giantim Apr 4, 2020
51b12f0
refactor: 프로그램 실행 시 재귀 로직 제거 / 테스트 메서드를 작은 단위 테스트로 분리 / 승자가 결정되지 않았을 …
giantim Apr 5, 2020
48d1654
Merge branch 'mission2' into web-chess
giantim Apr 5, 2020
8ccb3fc
Merge pull request #4 from giantim/web-chess
giantim Apr 5, 2020
dd4951d
refactor: 웹에서 점수 출력 시 black, white 둘 다 출력 되도록 변경 / 왕을 잡아서 게임이 끝날 시 종료…
giantim Apr 5, 2020
80f6821
refactor: 콘솔에서 status 명령 입력 시 양 팀의 점수 모두 계산해 출력 / 컨벤션 수정 / 상수 추출
giantim Apr 5, 2020
fec5fe5
feat: ChessBoard 추가 테스트
giantim Apr 5, 2020
130853c
feat: 가장 최근에 추가된 ChessBoard 찾는 기능 추가
giantim Apr 5, 2020
d435afa
feat: 가장 최근에 추가 된 ChessBoard 삭제 기능 구현
giantim Apr 5, 2020
254c5ed
feat: 피스 정보 추가, 업데이트, 삭제 구현
giantim Apr 5, 2020
cafcd69
feat: 데이터베이스에서 피스 정보 불러오기 - (1)
giantim Apr 5, 2020
4ca0307
feat: db 에서 읽은 값으로 각 피스 초기화
giantim Apr 6, 2020
8990ebb
feat: 현재 팀 정보 데이터베이스에 저장 구현
giantim Apr 6, 2020
72a35ba
feat: 게임 시작 또는 체스 게임 불러오기 기능 구현
giantim Apr 6, 2020
b1ce5b9
feat: 이동 후의 결과 데이터베이스에 업데이트 구현(포지션 이름 매핑 수정필요)
giantim Apr 6, 2020
89c93db
feat: 이동 후에 정보를 저장해 서버 종료 후에도 게임 진행 가능하게 구현
giantim Apr 6, 2020
f4efb98
feat: end 버튼 누를 시 양 팀의 점수를 계산해서 보여주고 종료 / 한 팀이 다른 팀의 왕을 잡았을 때 데이터 베이스…
giantim Apr 6, 2020
fd4d78e
refactor: 웹의 체스 보드의 각 칸마다 위치 값 표시
giantim Apr 6, 2020
a2c8745
refactor: 불필요한 Piece 정보 수정 메서드 삭제 / 컨벤션 수정 / 테스트 코드에 맞게 데이터 형식 변경
giantim Apr 6, 2020
ca89964
feat: 플레이어 입력, 게임 방을 위한 뷰 구현
giantim Apr 7, 2020
352729a
feat: 플레이어 정보 저장, 검색, 삭제 기능 구현
giantim Apr 7, 2020
f6ae741
feat: 기존의 게임 정보 불러오기 구현
giantim Apr 7, 2020
f46bc67
feat: 게임 목록에서 불러오기 기능 구현(1)
giantim Apr 7, 2020
3fef558
feat: 게임 목록에서 불러오기 기능 구현(2) - 데이터 불러오기 기능 구현
giantim Apr 8, 2020
2e747b9
feat: 종료 기능 구현
giantim Apr 8, 2020
6fe417b
refactor: DAO 의 코드 수정 / 연결하는 DB 변경
giantim Apr 8, 2020
23b2f34
refactor: Service Layer 추가 / DAO, DTO 패키지 이동
giantim Apr 9, 2020
44888f8
refactor: DAO 에 try-with-resources 적용
giantim Apr 9, 2020
c21faed
refactor: service layer 추가
giantim Apr 9, 2020
65e1171
refactor: controller 에 dao 를 이용하는 역할 제거
giantim Apr 13, 2020
a358f99
refactor: piece -> pieceOnBoard 모델로 변경
giantim Apr 13, 2020
d1bbe30
refactor: 신규 게임 시작 기능 수정
giantim Apr 13, 2020
9530093
refactor: controller 의 기능을 Service layer 로 분리
giantim Apr 13, 2020
a3629ac
refactor: Optional 객체의 null 검사 로직 추가
giantim Apr 13, 2020
7cdbc88
refactor: 메서드 위치 수정
giantim Apr 13, 2020
4360c88
Merge pull request #5 from giantim/web-chess
giantim Apr 13, 2020
e145ae0
refactor: ResultSet, PreparedStatement 닫는 구문 추가
giantim Apr 16, 2020
3a7ba78
refactor: 체스 게임 화면에 현재 진행중인 게임 id 출력하게 변경
giantim Apr 16, 2020
5d5d8c5
refactor: 서비스 내의 상태를 갖는 객체의 생명주기를 메서드 단위로 수정
giantim Apr 16, 2020
df0e3ed
refactor: DAO 가 도메인 자료 구조를 사용하도록 변경
giantim Apr 16, 2020
f25d61b
refactor: TileDTO, BoardScoreDTO 의 setter 메서드 삭제
giantim Apr 16, 2020
5170429
refactor: SQLException 에 대한 Custom RuntimeException 을 만들어서 예외 페이지 출력
giantim Apr 16, 2020
e5b625f
refactor: findFirst 를 Optional 로 래핑한 부분 수정
giantim Apr 19, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dependencies {
compile('ch.qos.logback:logback-classic:1.2.3')
testCompile('org.junit.jupiter:junit-jupiter:5.6.0')
testCompile('org.assertj:assertj-core:3.15.0')
compile("mysql:mysql-connector-java:8.0.16")
}

test {
Expand Down
19 changes: 5 additions & 14 deletions src/main/java/chess/WebUIChessApplication.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
package chess;

import spark.ModelAndView;
import spark.template.handlebars.HandlebarsTemplateEngine;
import chess.controller.WebChessController;

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

import static spark.Spark.get;
import static spark.Spark.staticFiles;

public class WebUIChessApplication {
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));
staticFiles.location("/templates");
WebChessController webChessController = new WebChessController();
webChessController.playChess();
}
}
50 changes: 36 additions & 14 deletions src/main/java/chess/controller/ChessController.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
package chess.controller;

import chess.controller.dto.TeamDto;
import chess.domain.ChessRunner;
import chess.dto.TeamDTO;
import chess.view.ConsoleInputView;
import chess.view.ConsoleOutputView;
import chess.view.InputView;
import chess.view.OutputView;
import org.apache.commons.lang3.StringUtils;

import java.util.Optional;

public class ChessController {
private static InputView inputView = new ConsoleInputView();
private static OutputView outputView = new ConsoleOutputView();

public static void start() {
Command command = getCommand();
outputView.printGameRule();
Command command = getGameCommand();
if (command.isStart()) {
ChessRunner chessRunner = new ChessRunner();
GameController gameController = command.getGameController();
Expand All @@ -23,13 +26,22 @@ public static void start() {
}
}

private static Command getCommand() {
try {
return Command.of(inputView.askChessRun());
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
return getCommand();
private static Command getGameCommand() {
Optional<Command> command = Optional.empty();

do {
command = Command.of(inputView.askGameCommand());
} while (isEmptyCommand(command));
return command.get();
Copy link

Choose a reason for hiding this comment

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

Optional.get은 직접적으로 사용되지 않는게 좋아요.

}

private static boolean isEmptyCommand(Optional<Command> command) {
if (command.isPresent()) {
return false;
}

System.out.println("잘못된 명령어를 입력하였습니다.");
return true;
}

private static void runChessGame(Command command, ChessRunner chessRunner) {
Expand All @@ -41,19 +53,29 @@ private static void runChessGame(Command command, ChessRunner chessRunner) {

private static Command validateExecute(Command command, ChessRunner chessRunner) {
try {
String commands = inputView.askGameCommand();
command = Command.of(commands);
GameController gameController = command.getGameController();
gameController.execute(chessRunner, commands);
} catch (IllegalArgumentException e) {
command = executeByCommand(command, chessRunner);
} catch (IllegalArgumentException | ArrayIndexOutOfBoundsException e) {
System.out.println(e.getMessage());
}
return command;
}

private static Command executeByCommand(Command command, ChessRunner chessRunner) {
String input = inputView.askGameCommand();
Optional<Command> inputCommand = Command.of(input);

while (isEmptyCommand(inputCommand)) {
input = inputView.askGameCommand();
inputCommand = Command.of(input);
}
command = inputCommand.get();
command.execute(chessRunner, input);
return command;
}

private static void printWinner(ChessRunner chessRunner) {
if (chessRunner.isEndChess()) {
TeamDto teamDto = new TeamDto(chessRunner.getWinner());
TeamDTO teamDto = new TeamDTO(chessRunner.getWinner());
outputView.printWinner(teamDto.getTeamName());
}
}
Expand Down
12 changes: 9 additions & 3 deletions src/main/java/chess/controller/Command.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package chess.controller;

import chess.domain.ChessRunner;

import java.util.Arrays;
import java.util.Optional;

public enum Command {
START("start", new StartController()),
Expand All @@ -16,11 +19,10 @@ public enum Command {
this.gameController = gameController;
}

public static Command of(final String command) {
public static Optional<Command> of(final String command) {
return Arrays.stream(values())
.filter(c -> command.contains(c.command))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("잘못된 명령어를 입력하였습니다."));
.findFirst();
}

public boolean isStart() {
Expand All @@ -34,4 +36,8 @@ public GameController getGameController() {
public boolean isEnd() {
return this == END;
}

public void execute(ChessRunner chessRunner, String commands) {
this.gameController.execute(chessRunner, commands);
}
}
8 changes: 4 additions & 4 deletions src/main/java/chess/controller/GameController.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package chess.controller;

import chess.controller.dto.BoardDto;
import chess.controller.dto.PositionDto;
import chess.domain.ChessRunner;
import chess.domain.position.Position;
import chess.dto.BoardDTO;
import chess.dto.PositionDTO;
import chess.view.ConsoleOutputView;
import chess.view.OutputView;

Expand All @@ -17,8 +17,8 @@ public GameController() {
}

protected void printBoard(final Map<String, String> board) {
BoardDto boardDto = new BoardDto(board);
PositionDto positionDto = new PositionDto(Position.getPositions());
BoardDTO boardDto = new BoardDTO(board);
PositionDTO positionDto = new PositionDTO(Position.getPositions());
this.outputView.printBoard(positionDto.getPositions(), boardDto.get());
}

Expand Down
18 changes: 13 additions & 5 deletions src/main/java/chess/controller/StatusController.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
package chess.controller;

import chess.controller.dto.BoardScoreDto;
import chess.controller.dto.TeamDto;
import chess.domain.ChessRunner;
import chess.dto.BoardScoreDTO;

import java.util.List;
import java.util.stream.Collectors;

public class StatusController extends GameController {
private static final String DELIMITER = ": ";
private static final String NEW_LINE = "\n";

public StatusController() {
super();
}

@Override
public void execute(ChessRunner chessRunner, String input) {
BoardScoreDto boardScoreDto = new BoardScoreDto(chessRunner.calculateScore());
TeamDto teamDto = new TeamDto(chessRunner.getCurrentTeam());
outputView.printStatus(boardScoreDto.getBoardScore(), teamDto.getTeamName());
List<BoardScoreDTO> boardScoreDtos = chessRunner.calculateScores();
String scores = boardScoreDtos.stream()
.map(dto -> dto.getTeam() + DELIMITER + dto.getBoardScore())
.collect(Collectors.joining(NEW_LINE));

outputView.printStatus(scores);
printBoard(chessRunner.getBoardEntities());
}
}
181 changes: 181 additions & 0 deletions src/main/java/chess/controller/WebChessController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
package chess.controller;

import chess.dao.ChessBoard;
import chess.dao.CustomSQLException;
import chess.dao.Player;
import chess.dto.MoveResultDTO;
import chess.dto.TeamDTO;
import chess.dto.TileDTO;
import chess.service.ChessService;
import spark.ModelAndView;
import spark.template.handlebars.HandlebarsTemplateEngine;

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

import static spark.Spark.get;
import static spark.Spark.post;

public class WebChessController {
private ChessService chessService;

public void playChess() {
this.chessService = new ChessService();

get("/", (req, res) -> {
Map<String, Object> model = new HashMap<>();

return render(model, "index.html");
});

post("/name", (req, res) -> {
Map<String, Object> model = new HashMap<>();

return render(model, "name.html");
});

post("/load", (req, res) -> {
Map<String, Object> model = new HashMap<>();

try {
List<Player> players = this.chessService.players();

model.put("gameData", players);

return render(model, "table.html");
} catch (CustomSQLException e) {
model.put("errMessage", e.getMessage());
return render(model, "error.html");
}
});

post("/newGame", (req, res) -> {
Map<String, Object> model = new HashMap<>();

String whitePlayer = req.queryParams("white-player");
String blackPlayer = req.queryParams("black-player");

try {
Player player = new Player(whitePlayer, blackPlayer);
this.chessService.newGame(player);
List<TileDTO> tileDtos = this.chessService.getTiles();
TeamDTO teamDto = this.chessService.getCurrentTeam();
ChessBoard chessBoard = this.chessService.getRecentChessBoard();

model.put("tiles", tileDtos);
model.put("currentTeam", teamDto);
model.put("player", player);
model.put("chessBoard", chessBoard);

return render(model, "game.html");
} catch (CustomSQLException e) {
model.put("errMessage", e.getMessage());
return render(model, "error.html");
}
});

post("/continueGame", (req, res) -> {
Map<String, Object> model = new HashMap<>();

int chessBoardId = Integer.parseInt(req.queryParams("chess-board-id"));

try {
this.chessService.continueGame(chessBoardId);
List<TileDTO> tileDtos = this.chessService.getTiles();
TeamDTO teamDto = this.chessService.getCurrentTeam();
Player player = this.chessService.getPlayer(chessBoardId);
ChessBoard chessBoard = new ChessBoard(chessBoardId);

model.put("tiles", tileDtos);
model.put("currentTeam", teamDto);
model.put("player", player);
model.put("chessBoard", chessBoard);

return render(model, "game.html");
} catch (CustomSQLException e) {
model.put("errMessage", e.getMessage());
Comment on lines +96 to +97
Copy link

Choose a reason for hiding this comment

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

그냥 모든 예외를 잡아 처리하도록 하여
http://sparkjava.com/documentation#error-handling
해당 기능을 활용했어도 좋았을 것 같네요. :)

return render(model, "error.html");
}
});

post("/move", (req, res) -> {
Map<String, Object> model = new HashMap<>();

int chessBoardId = Integer.parseInt(req.queryParams("chess-board-id"));
String source = req.queryParams("source");
String target = req.queryParams("target");

try {
MoveResultDTO moveResultDto = this.chessService.move(chessBoardId, source, target);
List<TileDTO> tileDtos = this.chessService.getTiles();
TeamDTO teamDto = this.chessService.getCurrentTeam();
Player player = this.chessService.getPlayer(chessBoardId);
ChessBoard chessBoard = new ChessBoard(chessBoardId);

model.put("tiles", tileDtos);
model.put("currentTeam", teamDto);
model.put("message", moveResultDto.getMessage());
model.put("style", moveResultDto.getStyle());
model.put("player", player);
model.put("chessBoard", chessBoard);

if (this.chessService.isEndGame()) {
this.chessService.deleteChessGame(chessBoardId);
return render(model, "end.html");
}
return render(model, "game.html");
} catch (CustomSQLException e) {
model.put("errorMessage", e.getMessage());
return render(model, "error.html");
}
});

post("/status", (req, res) -> {
Map<String, Object> model = new HashMap<>();

int chessBoardId = Integer.parseInt(req.queryParams("chess-board-id-status"));

try {
List<TileDTO> tileDtos = this.chessService.getTiles();
TeamDTO teamDto = this.chessService.getCurrentTeam();
String message = this.chessService.getScores();
Player player = this.chessService.getPlayer(chessBoardId);
ChessBoard chessBoard = new ChessBoard(chessBoardId);

model.put("tiles", tileDtos);
model.put("currentTeam", teamDto);
model.put("message", message);
model.put("player", player);
model.put("chessBoard", chessBoard);

return render(model, "game.html");
} catch (CustomSQLException e) {
model.put("errorMessage", e.getMessage());
return render(model, "error.html");
}
});

post("/end", (req, res) -> {
Map<String, Object> model = new HashMap<>();

int chessBoardId = Integer.parseInt(req.queryParams("chess-board-id-end"));

try {
this.chessService.deleteChessGame(chessBoardId);
String message = this.chessService.getScores();

model.put("message", message);

return render(model, "end.html");
} catch (CustomSQLException e) {
model.put("errorMessage", e.getMessage());
return render(model, "error.html");
}
});
}

private static String render(Map<String, Object> model, String templatePath) {
return new HandlebarsTemplateEngine().render(new ModelAndView(model, templatePath));
}
}
Loading