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단계 미션 제출합니다. #195

Merged
merged 22 commits into from
May 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
31cfa7b
docs: README.md 수정 - 레벨 4
toneyparky Apr 29, 2020
1839c71
feat: 데이터베이스 스키마 업데이트
toneyparky Apr 29, 2020
c8c9d31
feat: 테스트용 데이터베이스 설정
toneyparky Apr 29, 2020
d332025
feat: 게임 생성 후 DB에 저장 기능 구현
toneyparky Apr 29, 2020
520568e
feat: 게임 DB에 조회 기능 구현
toneyparky Apr 29, 2020
f8faa6b
style: 컨벤션을 위한 수정
toneyparky Apr 29, 2020
9fd31b8
feat: game 업데이트 기능 구현
toneyparky Apr 29, 2020
2435e2d
feat: history 추가 구현
toneyparky Apr 29, 2020
050afe4
feat: Game에 해당하는 히스토리 전체 조회
toneyparky Apr 29, 2020
66f72e8
fix: 종료된 게임은 전체 조회 목록에서 제외하도록 수정
toneyparky Apr 29, 2020
e81e513
feat: 게임을 생성하고 해당 게임을 불러오는 기능 추가
toneyparky May 1, 2020
7f2ad79
style: javascript 컨벤션을 지키기 위해 4칸에서 2칸으로 탭 수정
toneyparky May 1, 2020
940776c
feat: move와 loading 관련 api에 gameId를 이용하도록 구현
toneyparky May 1, 2020
fec4be2
feat: 게임이 종료되면 결과 페이지로 넘어가는 기능 구현
toneyparky May 1, 2020
c742427
feat: 진행가능한 게임 목록을 보여주는 기능 구현
toneyparky May 4, 2020
a7e61d6
feat: 게임 중 나가기 기능 추가
toneyparky May 4, 2020
671275c
refactor: 사용하지 않는 레포지토리 제거
toneyparky May 4, 2020
c8321e5
style: index.hbs 뷰 수정
toneyparky May 4, 2020
819034e
style: chess.hbs, result.hbs 뷰 수정
toneyparky May 4, 2020
485b2b8
fix: 게임 이름을 입력하지 않으면 빈 보드로 넘어가는 버그 수정
toneyparky May 4, 2020
7247b44
style: 프로젝트 전체 파일 컨벤션 수정
toneyparky May 4, 2020
22c8587
fix: 사용자가 데이터베이스에 저장되어 있지 않은 게임 아이디로 정보를 전달할 때 예외 처리 기능 구현
toneyparky May 4, 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
32 changes: 30 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,34 @@
# 체스 3단계 - Spring Data JDBC 적용하기

## **프로그래밍 요구사항**
- Spring Data JDBC를 활용하여 기존에 사용하던 DB에 접근하기
- Spring Data JDBC를 활용하여 기존에 사용하던 DB에 접근하기.
- 엔티티 클래스를 만들어 DB 테이블과 맵핑한다.
- Spring Data JDBC에서 제공하는 Repository를 활용하여 DB에 접근한다.
- Spring Data JDBC에서 제공하는 Repository를 활용하여 DB에 접근한다.

# 체스 4단계 - 동시에 여러 게임 하기

## **프로그래밍 요구사항**
- 체스 게임을 진행할 수 있는 방을 만들어서 동시에 여러 게임이 가능하도록 하기.

### 체스방 만들기

- localhost:8080 요청 시 노출되는 페이지에 체스방을 만들 수 있는 버튼이 있다.
- 체스방 이름 입력하기 input을 추가한다.
- 체스방 만들기 버튼을 누르면 새로운 체스판이 초기화 된다.
- 체스방에는 고유식별값이 랜덤으로 부여된다.

### 체스방 목록 조회하기

- localhost:8080 요청 시 체스방 목록을 조회할 수 있다
- 체스방 목록에는 체스방 제목이 표시된다.
- 방법은 '/'로 GET 요청을 보내면 체스방에 대한 JSON이 반환된다.
- 그리고 해당 JSON을 index.js에서 처리하여 보여준다.

### 체스방 참여하기

- localhost:8080 요청 시 체스방 목록에서 체스방을 클릭하면 체스 게임을 이어서 진행할 수 있다.

### 엔티티

- Game : id(auto increment), UUID, name, canContinue
- History : id, start, end, gameId
1 change: 0 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ dependencies {
implementation 'net.rakugakibox.spring.boot:logback-access-spring-boot-starter:2.7.1'
implementation 'pl.allegro.tech.boot:handlebars-spring-boot-starter:0.3.1'
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'com.google.code.gson:gson:2.8.6'
compile('com.sparkjava:spark-core:2.9.0')
compile('com.sparkjava:spark-template-handlebars:2.7.1')
compile('ch.qos.logback:logback-classic:1.2.3')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ private String postBoard(Request req, Response res) {
Map<String, Object> model = new HashMap<>();

try {
MoveStatusDto moveStatusDto = sparkChessService.move(new MovingPosition(req.queryParams("source"), req.queryParams("destination")));
MoveStatusDto moveStatusDto = sparkChessService.move(new MovingPosition(req.queryParams("source"),
req.queryParams("destination")));

model.put("normalStatus", moveStatusDto.getNormalStatus());
model.put("winner", moveStatusDto.getWinner());
Expand Down Expand Up @@ -108,7 +109,8 @@ private Map<String, Object> getMovablePositions(Request req, Response res) throw
private Map<String, Object> move(Request req, Response res) {
Map<String, Object> model = new HashMap<>();

DestinationPositionDto destinationPositionDto = sparkChessService.chooseDestinationPosition(req.queryParams("destination"));
DestinationPositionDto destinationPositionDto = sparkChessService.chooseDestinationPosition(
req.queryParams("destination"));

model.put("normalStatus", destinationPositionDto.getNormalStatus().isNormalStatus());
model.put("position", destinationPositionDto.getPosition());
Expand Down
161 changes: 91 additions & 70 deletions src/main/java/wooteco/chess/controller/SpringChessController.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,94 +7,115 @@
import wooteco.chess.domain.game.NormalStatus;
import wooteco.chess.domain.position.MovingPosition;
import wooteco.chess.dto.ChessGameDto;
import wooteco.chess.dto.GamesDto;
import wooteco.chess.dto.MovablePositionsDto;
import wooteco.chess.dto.MoveStatusDto;
import wooteco.chess.service.SpringDataJDBCChessService;
import wooteco.chess.web.JsonTransformer;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

@Controller
public class SpringChessController {
@Autowired
private SpringDataJDBCChessService springChessService;
@Autowired
private SpringDataJDBCChessService springDataJDBCChessService;

Choose a reason for hiding this comment

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

https://madplay.github.io/post/why-constructor-injection-is-better-than-field-injection

의존성 주입에 대한 방법에 대해 생각해보면 좋을 것 같아요 :)


@GetMapping("/")
public ModelAndView routeMainPage() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("index");
modelAndView.addObject("normalStatus", NormalStatus.YES.isNormalStatus());
return modelAndView;
}
@GetMapping("/")
public ModelAndView routeMainPage() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("index");
modelAndView.addObject("normalStatus", NormalStatus.YES.isNormalStatus());
return modelAndView;
}

@GetMapping("/new")
public ModelAndView startNewGame() throws SQLException {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("chess");
modelAndView.addObject("normalStatus", NormalStatus.YES.isNormalStatus());
springChessService.clearHistory();
return modelAndView;
}
@GetMapping("/games")
@ResponseBody
public String showGames() {
GamesDto games = springDataJDBCChessService.selectAvailableGames();
return JsonTransformer.toJson(games);
}

@GetMapping("/board")
@ResponseBody
public String setBoard() throws SQLException {
ChessGameDto chessGameDto = springChessService.setBoard();
return JsonTransformer.toJson(chessGameDto);
}
@PostMapping("/new")
@ResponseBody
public String saveNewGame(@RequestBody Map<String, Object> param) {
System.out.println(param.get("gameName"));
ChessGameDto chessGameDto = springDataJDBCChessService.createGameBy((String) param.get("gameName"));

@GetMapping("/source")
@ResponseBody
public String getMovablePositions(@RequestParam String source) throws SQLException {
Map<String, Object> model = new HashMap<>();
try {
MovablePositionsDto movablePositionsDto = springChessService.findMovablePositions(source);
model.put("movable", movablePositionsDto.getMovablePositionNames());
model.put("position", movablePositionsDto.getPosition());
model.put("normalStatus", NormalStatus.YES.isNormalStatus());
return JsonTransformer.toJson(model);
} catch (IllegalArgumentException | UnsupportedOperationException | NullPointerException e) {
model.put("normalStatus", NormalStatus.NO.isNormalStatus());
model.put("exception", e.getMessage());
return JsonTransformer.toJson(model);
}
}
return JsonTransformer.toJson(chessGameDto);
}

@GetMapping("/destination")
@ResponseBody
public String checkMovable(@RequestParam String startPosition, @RequestParam String destination) {
Map<String, Object> model = new HashMap<>();
MoveStatusDto moveStatusDto = springChessService.checkMovable(
new MovingPosition(startPosition, destination));
@GetMapping("/game/{id}")
@ResponseBody
public ModelAndView startGame() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("chess");
modelAndView.addObject("normalStatus", NormalStatus.YES.isNormalStatus());
return modelAndView;
}

model.put("normalStatus", moveStatusDto.getNormalStatus());
model.put("exception", moveStatusDto.getException());
return JsonTransformer.toJson(model);
}
@GetMapping("/board/{id}")
@ResponseBody
public String setBoard(@PathVariable Long id) {
ChessGameDto chessGameDto = springDataJDBCChessService.setBoardBy(id);
return JsonTransformer.toJson(chessGameDto);
}

@PostMapping("/board")
public ModelAndView saveHistory(@RequestBody MovingPosition movingPosition) throws SQLException {
ModelAndView modelAndView = new ModelAndView();
@GetMapping("/board/{id}/source")
@ResponseBody
public String getMovablePositions(@PathVariable Long id, @RequestParam String source) {
Map<String, Object> model = new HashMap<>();
try {
MovablePositionsDto movablePositionsDto = springDataJDBCChessService.findMovablePositions(id, source);
model.put("movable", movablePositionsDto.getMovablePositionNames());
model.put("position", movablePositionsDto.getPosition());
model.put("normalStatus", NormalStatus.YES.isNormalStatus());
return JsonTransformer.toJson(model);
} catch (IllegalArgumentException | UnsupportedOperationException | NullPointerException e) {
model.put("normalStatus", NormalStatus.NO.isNormalStatus());
model.put("exception", e.getMessage());
return JsonTransformer.toJson(model);
}
}

MoveStatusDto moveStatusDto = springChessService.move(movingPosition);
if (moveStatusDto.getWinner().isNone()) {
modelAndView.setViewName("chess");
return modelAndView;
}
modelAndView.setViewName("result");
modelAndView.addObject("winner", moveStatusDto.getWinner());
springChessService.clearHistory();
return modelAndView;
}
@GetMapping("/board/{id}/destination")
@ResponseBody
public String checkMovable(@PathVariable Long id, @RequestParam String startPosition,
@RequestParam String destination) {
Map<String, Object> model = new HashMap<>();
MoveStatusDto moveStatusDto = springDataJDBCChessService.checkMovable(id,
new MovingPosition(startPosition, destination));

@GetMapping("/loading")
public ModelAndView loadGame() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("chess");
modelAndView.addObject("normalStatus", NormalStatus.YES.isNormalStatus());
model.put("normalStatus", moveStatusDto.getNormalStatus());
model.put("exception", moveStatusDto.getException());
return JsonTransformer.toJson(model);
}

return modelAndView;
}
@PostMapping("/board/{id}")
@ResponseBody
public String saveHistory(@PathVariable Long id, @RequestBody MovingPosition movingPosition) {
try {
MoveStatusDto moveStatusDto = springDataJDBCChessService.move(id, movingPosition);
return JsonTransformer.toJson(moveStatusDto);
} catch (IllegalArgumentException e) {
MoveStatusDto moveStatusDto = new MoveStatusDto(false, e.getMessage());
return JsonTransformer.toJson(moveStatusDto);
}
}

@GetMapping("/loading/{id}")
public ModelAndView loadGame() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("chess");
modelAndView.addObject("normalStatus", NormalStatus.YES.isNormalStatus());
return modelAndView;
}

@GetMapping("/result/{winner}")
public ModelAndView showResult(@PathVariable String winner) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("result");
modelAndView.addObject("winner", winner);
return modelAndView;
}
}
3 changes: 2 additions & 1 deletion src/main/java/wooteco/chess/dto/BoardDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import wooteco.chess.domain.piece.pieces.Pieces;
import wooteco.chess.domain.position.Position;

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

Expand All @@ -17,6 +18,6 @@ public BoardDto(Pieces pieces) {
}

public Map<Position, PieceDto> getBoard() {
return board;
return Collections.unmodifiableMap(board);
}
}
21 changes: 17 additions & 4 deletions src/main/java/wooteco/chess/dto/ChessGameDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
import wooteco.chess.domain.game.Turn;

public class ChessGameDto {
private BoardDto boardDto;
private Turn turn;
private ScoreResult score;
private boolean normalStatus;
private Long gameId;
private final BoardDto boardDto;
private final Turn turn;
private final ScoreResult score;
private final boolean normalStatus;

public ChessGameDto(BoardDto boardDto, Turn turn, ScoreResult score, boolean normalStatus) {
this.boardDto = boardDto;
Expand All @@ -16,6 +17,18 @@ public ChessGameDto(BoardDto boardDto, Turn turn, ScoreResult score, boolean nor
this.normalStatus = normalStatus;
}

public ChessGameDto(Long gameId, BoardDto boardDto, Turn turn, ScoreResult score, boolean normalStatus) {
this.gameId = gameId;
this.boardDto = boardDto;
this.turn = turn;
this.score = score;
this.normalStatus = normalStatus;
}

public Long getGameId() {
return gameId;
}

public BoardDto getBoardDto() {
return boardDto;
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/wooteco/chess/dto/DestinationPositionDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import wooteco.chess.domain.game.NormalStatus;

public class DestinationPositionDto {
private String position;
private NormalStatus normalStatus;
private final String position;
private final NormalStatus normalStatus;

public DestinationPositionDto(String position, NormalStatus normalStatus) {
this.position = position;
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/wooteco/chess/dto/GamesDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package wooteco.chess.dto;

import java.util.Collections;
import java.util.Map;

public class GamesDto {
private final Map<Long, String> games;

public GamesDto(Map<Long, String> games) {
this.games = games;
}

public Map<Long, String> getGames() {
return Collections.unmodifiableMap(games);
}
}
7 changes: 4 additions & 3 deletions src/main/java/wooteco/chess/dto/MovablePositionsDto.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
package wooteco.chess.dto;

import java.util.Collections;
import java.util.List;

public class MovablePositionsDto {
private List<String> movablePositionNames;
private String position;
private final List<String> movablePositionNames;
private final String position;

public MovablePositionsDto(List<String> movablePositionNames, String position) {
this.movablePositionNames = movablePositionNames;
this.position = position;
}

public List<String> getMovablePositionNames() {
return movablePositionNames;
return Collections.unmodifiableList(movablePositionNames);
}

public String getPosition() {
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/wooteco/chess/dto/MoveStatusDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
public class MoveStatusDto {
private static final String EMPTY_STRING = "";

private boolean normalStatus;
private Color winner;
private String exception;
private final boolean normalStatus;
private final Color winner;
private final String exception;

public MoveStatusDto(boolean normalStatus, String exception) {
this.normalStatus = normalStatus;
Expand Down
Loading