Skip to content

Commit

Permalink
[임루트] 체스 스프링 실습 4단계 제출합니다. (#177)
Browse files Browse the repository at this point in the history
* [동글] 체스 스프링 실습 1단계 미션 제출합니다. (#28)

* Initial commit

* initial commit

* upgrade library version, config useJUnitPlatform

* [동글] 체스 미션 1주차 제출합니다. (#87)

* [Test] 테스트란다

* docs: 기능 구현 목록 생성

* feat: 위치 객체 생성

* feat: Position 캐싱 적용

* feat: Position 캐싱 추가 구현

* test: 체스말 테스트 코드 추가

* feat: 게임 말, 폰, 팀 클래스 추가

* feat: 모든 종류 체스말 클래스 생성

* feat: 명령어 enum 추가

* docs: README 수정

* refactor: Piece 내의 Position 제거

* feat: 체스 말 도달 가능 경로 반환 로직 추가

* feat: 직선경로 여부 판단로직 추가

* feat: 두 체스말의 행이 일치하는지 확인하는 기능 구현

* feat: 두 위치의 행이 일치하는 경우 경로 계산

* docs: 기능목록 수정

* feat: 보드 클래스 추가

* test: Board의 생성 테스트 작성

* feat: 보드 위 체스말 이동 기능 추가

* feat: MoveValidStrategy 클래스 생성

* feat: 주어진 경로(List<Position>)안에 말이 있는지 판별하는 로직 추가

* test: 체스말의 경로 이동 가능 여부 테스트 추가

* feat: 랭크 대소 비교 로직 추가

* feat: 파일(열) 비교 로직 추가

* refactor: PieceTest를 PawnTest와 RookTest로 분리

* feat: string을 통해 File 객체 찾기 추가

* refactor: Strategy관련 코드 삭제, Board내부로 체스말 이동 로직 옮김

* feat: 흑팀 체스말 초기화

* feat: 백팀 체스말 초기화, View 생성

* feat: 체스판 출력 기능

* feat: Team판별 로직 추가

* feat: 체스판 출력 기능 보완

* feat: 컨트롤러 생성

* feat: 게임 명령어 입력 기능 추가

* feat: 1단계 완료

* feat: 게임 시작 메시지 출력 메서드 추가

* feat: controller에 while문 추가

* feat: 이동할 좌표 입력 메서드 추가

* feat: 비숍 이동 여부 확인 기능 추가

* feat: 주어진 두 위치가 대각선인지 확인하는 로직 추가

* feat: 비숍의 좌상 대각선 방면 경로 확인 기능

* feat: 대각선 위치의 두 Position의 경로를 찾는 메서드 추가

* test: 비숍이동 로직 테스트 작성

* feat: 대각선 위치의 두 Position의 경로를 찾는 메서드 구현

* feat: 퀸 이동 기능 구현

* test: 퀸, 나이트, 킹 테스트 코드 추가

* feat: King 이동 가능 여부 판단 메서드 생성

* feat: King 이동 가능 여부 판단 메서드 구현

* feat: Knight 이동 가능 여부 판단 메서드 구조 구현

* test: Pawn 테스트 코드 작성

* test: Pawn의 첫 움직임 테스트 코드 작성

* test: Pawn 두칸 이동시 첫이동 여부 확인

* feat: Pawn의 움직임이 유효한지 체크하는 로직 추가

* feat: Pawn의 이동경로 반환 기능 구현

* feat: 상대 말을 잡는 로직 생성

* refactor: Bishop 이동경로 구하는 로직 변경

* feat: King, Knight 이동경로 구하는 로직 변경

* feat: 두 Position 사이의 모든 Position들을 반환하는 메서드 추가

* fix: Pawn 이동 로직 버그 수정

* fix: 테스트코드 fail 해결

* feat: 게임 종료 기능 구현

* refactor: 반복 조건 변경

* feat: 점수계산, 킹 잡힘 여부 확인 로직 수정

* feat: 기물의 이동과 기물의 catch 분리, 폰 움직임 버그 수정

* refactor: 개선된 보드 클래스 적용

* refactor: 메서드 포장

* feat: 현재 남아있는 체스말 기준 팀별 점수 계산 구현

* feat: 게임중 예외 발생시 명령어 재 입력 기능

* feat: Position 행, 열 중복 제거

* fix: 테스트 코드 버그 수정

* refactor: 일부 메서드 이름 수정

* refactor: 불필요 클래스 제거

* feat: 웹 UI 추가, 게임 시작시 , 게임 판 초기화, 점수판 갱신

* feat: 체스게임 상태 패턴 적용, 명령어별 컨트롤러 실행로직 enum 집중화

* test: 테스트 케이스 추가

* test: 테스트 케이스 추가

* fix: 킹이 잡혀서 게임이 끝나는 경우, 승자 출력안되는 버그 수정

* test: command 테스트 케이스 추가

Co-authored-by: 황준호 <42054054+hwanghe159@users.noreply.github.com>

* [동글] 체스 웹/DB 미션 제출합니다. (#152)

* refactor: 일부 클래스, 메소드 이름 변경, 메서드 추출, Board 일부 로직 변경

* feat: 팀별 점수 계산 기능 클래스 추출

* feat: 체스 기물 이미지 추가

* feat: 팀별 점수 반환기능 추가

* style: code formatting

* feat: 보드위 놓여있는 모든 기물 dto 목록 반환 기능 추가

* feat: 보드위 기물 이동 기능, 변화 생긴 지점 BoardDTO 목록 반환 기능 추가

* feat: 웹 UI  체스말 이동 기능 추가

* fix: 게임 중간에 재시작을 누르는 경우, 게임턴이 백팀으로 초기화 되지 않는 버그 수정

* feat: 체스 말 이동 기능 추가

* fix: 체스 기물 이미지 클릭시, cell이 클릭 되지 않는 버그 수정

* feat: 웹상 게임 상태 종료 여부 체크, 조건에 따른 게임 종료 기능 추가

* feat: data base 연결 추가

* docs: 기능목록 구현 갱신

* refactor: http api response 구조 변경 위한 response 관련 클래스 추가

* refactor: 응답 json 데이터 응답상태, 데이터, 메시지 형태로 포맷화

* refactor: dao에서 사용하는 jdbc 공통 로직 jdbctemplate로 분리

* fix: jdbc template out of bound index exception 버그 수정

* refactor: controller 모든 응답 내 try-catch 문 중복 제거

* refactor: jdbc template 내 중복 제거, DAO find 반환 타입 optional 변경

* refactor: 게임 상태 변경 요청 로직내 if-else 문 중복 제거

* refactor: 상태 값 반환 타입 enum 에서 string 으로 변경

* refactor: index 페이지 랜더링 객체 static 변수로 미리 생성

* refactor: 문자열 -> board 객체 파싱로직 리팩토링, 생성자 인자 null 검증 추가

* refactor: 점수 계산 기능 Result 객체로 위임

* refactor: 피드백 반영

* refactor: js 함수들 변수로 표현

* test: service 테스트 추가

* chore : 기존 체스 구현 가져옴

* refactor : 이동경로 반환 전략 적용

* refactor : 보드를 파싱하는 로직을 분리

* refactor : StateType enum 제거

* refactor : GameState을 Game으로 수정

* Board 에서 parseString() 지우기

* refactor : 패키지 구조 변경 및 import 문 정리

* refactor : board parser 매직넘버 제거, 변수명 변경

Co-authored-by: 박재성 <pobi@woowahan.com>
Co-authored-by: 황준호 <42054054+hwanghe159@users.noreply.github.com>

* [동글] 스프링 실습 2단계 미션 제출합니다. (#89)

* feat : spring 컨트롤러 작성

* feat : spring 컨트롤러 작성 완료

* refactor : 기존 예외처리 로직 controller에서 service로 이동, 알트 피드백 반영

* fix : 충돌 해결

* style : 자바 컨벤션에 맞도록 코드 수정

* fix : 병합 충돌 해결

* refactor : chess controller view, rest controller 로 분리

* [동글] 체스 스프링 실습 3단계 미션 제출합니다. (#114)

* feat : spring-data-jdbc 적용

* refactor : game 도메인 id 필드 제거

* refactor : game entity id getter 제거

* refactor : 피드백 반영

* feat : 식별자 랜덤 생성, 방생성, 여러 게임 기능

* refac: 또링 피드백 반영

Co-authored-by: taejinseok <46241671+taejinseok@users.noreply.github.com>
Co-authored-by: 박재성 <pobi@woowahan.com>
Co-authored-by: 황준호 <42054054+hwanghe159@users.noreply.github.com>
Co-authored-by: taejinseok <stj930@gmail.com>
  • Loading branch information
5 people committed May 4, 2020
1 parent eeec215 commit 89ec6d8
Show file tree
Hide file tree
Showing 14 changed files with 528 additions and 381 deletions.
24 changes: 24 additions & 0 deletions src/main/java/wooteco/chess/config/ChessConfiguration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package wooteco.chess.config;

import java.util.UUID;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.relational.core.mapping.event.BeforeSaveCallback;

import wooteco.chess.repository.jdbc.GameEntity;

@Configuration
public class ChessConfiguration {
@Bean
public BeforeSaveCallback<GameEntity> setRandomIdToEntity() {
return (aggregate, aggregateChange) -> {
aggregate.setIdIfIdIsNull(createNewId());
return aggregate;
};
}

private String createNewId() {
return UUID.randomUUID().toString();
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
package wooteco.chess.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@Controller
public class SpringChessController {
@GetMapping("/")
public String index() {
return "index";
}
}

@GetMapping("/game/{id}")
public String game(@PathVariable String id, Model model) {
model.addAttribute("id", id);
return "game";
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package wooteco.chess.controller;


import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import wooteco.chess.service.GameService;
import wooteco.chess.view.dto.requestdto.PositionRequestDto;
Expand All @@ -16,38 +21,48 @@ public SpringChessRestController(GameService gameService) {
this.gameService = gameService;
}

@GetMapping("/state")
public ResponseDto findCurrentState() {
return gameService.getCurrentState();
@GetMapping("/games")
public ResponseDto games() {
return gameService.findAllGameIds();
}

@PostMapping("/game")
public ResponseDto createNewGame() {
return gameService.createNewGame();
}

@GetMapping("/state/{id}")
public ResponseDto findCurrentState(@PathVariable String id) {
return gameService.getCurrentState(id);
}

@PostMapping("/state")
public ResponseDto changeState(@RequestBody String request) {
return gameService.changeState(request);
@PutMapping("/state/{id}")
public ResponseDto changeState(@RequestBody String request, @PathVariable String id) {
return gameService.changeState(id, request);
}

@GetMapping("/pieces")
public ResponseDto findAllPiecesOnBoard() {
return gameService.findAllPiecesOnBoard();
@GetMapping("/pieces/{id}")
public ResponseDto findAllPiecesOnBoard(@PathVariable String id) {
return gameService.findAllPiecesOnBoard(id);
}

@GetMapping("/record")
public ResponseDto calculateScore() {
return gameService.calculateScore();
@GetMapping("/record/{id}")
public ResponseDto calculateScore(@PathVariable String id) {
return gameService.calculateScore(id);
}

@PutMapping("/move")
public ResponseDto move(@RequestBody PositionRequestDto requestDTO) {
return gameService.move(requestDTO);
@PutMapping("/move/{id}")
public ResponseDto move(@RequestBody PositionRequestDto requestDTO, @PathVariable String id) {
return gameService.move(id, requestDTO);
}

@GetMapping("/isnotfinish")
public ResponseDto isNotFinish() {
return gameService.isNotFinish();
@GetMapping("/isnotfinish/{id}")
public ResponseDto isNotFinish(@PathVariable String id) {
return gameService.isNotFinish(id);
}

@GetMapping("/result")
public ResponseDto findWinner() {
return gameService.getWinner();
@GetMapping("/result/{id}")
public ResponseDto findWinner(@PathVariable String id) {
return gameService.getWinner(id);
}
}
}
12 changes: 12 additions & 0 deletions src/main/java/wooteco/chess/domain/board/BoardFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
public class BoardFactory {
private static final Pattern PIECES_PATTERN = Pattern.compile("([\\.pPbBrRkKnNqQ]{8}\\n){8}");
private static final String ILLEGAL_BOARD_REGEX_EXCEPTION_MESSAGE = "문자열의 형태가 체스판의 형식이 아닙니다.";
private static final String EMPTY_BOARD = "........\n"
+ "........\n"
+ "........\n"
+ "........\n"
+ "........\n"
+ "........\n"
+ "........\n"
+ "........\n";

private BoardFactory() {
}
Expand All @@ -25,4 +33,8 @@ private static void validateBoardRegex(String boards) {
throw new IllegalArgumentException(String.format(ILLEGAL_BOARD_REGEX_EXCEPTION_MESSAGE + "%s", boards));
}
}

public static Board ofEmpty() {
return create(EMPTY_BOARD);
}
}
6 changes: 3 additions & 3 deletions src/main/java/wooteco/chess/domain/game/Ready.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
import static wooteco.chess.domain.piece.Team.*;

import wooteco.chess.domain.board.Board;
import wooteco.chess.domain.board.BoardFactory;
import wooteco.chess.domain.piece.Team;
import wooteco.chess.domain.position.Position;
import wooteco.chess.domain.result.Result;

public class Ready extends Game {
public Ready(Board board) {
this(board, NONE);
}

public static final Ready READY_INSTANCE = new Ready(BoardFactory.ofEmpty(), NONE);

public Ready(Board board, Team turn) {
super(board, turn);
Expand Down
16 changes: 15 additions & 1 deletion src/main/java/wooteco/chess/repository/jdbc/GameEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
@Table("game")
public class GameEntity {
@Id
private int id;
private String id;
private String state;
private String turn;
private String board;
Expand All @@ -21,6 +21,20 @@ public GameEntity(String state, String turn, String board) {
this.board = board;
}

public static GameEntity of(Game game) {
return new GameEntity(game.getStateType(), game.getTurn().name(), BoardParser.parseString(game.getBoard()));
}

public void setIdIfIdIsNull(String id) {
if (this.id == null) {
this.id = id;
}
}

public String getId() {
return id;
}

public String getTurn() {
return turn;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package wooteco.chess.repository.jdbc;


import java.util.List;

import org.springframework.data.jdbc.repository.query.Query;
import org.springframework.data.repository.CrudRepository;

public interface GameRepository extends CrudRepository<GameEntity, Long> {
public interface GameRepository extends CrudRepository<GameEntity, String> {
@Query("SELECT id FROM game")
List<String> findAllIds();

}
46 changes: 29 additions & 17 deletions src/main/java/wooteco/chess/service/GameService.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package wooteco.chess.service;

import static wooteco.chess.domain.game.Ready.*;
import static wooteco.chess.view.response.ResponseStatus.*;

import java.util.ArrayList;
Expand All @@ -25,17 +26,16 @@
@Service
public class GameService {
private static final String NONE_ELEMENT_QUERY_RESULT_EXCEPTION_MESSAGE = "조건에 해당하는 요소가 없습니다.";
private static final Long DEFAULT_USER_ID = 1L;

private final GameRepository gameRepository;

public GameService(GameRepository gameRepository) {
this.gameRepository = gameRepository;
}

public ResponseDto calculateScore() {
public ResponseDto calculateScore(String gameId) {
return makeResponse(() -> {
Game game = findGame();
Game game = findGame(gameId);
Result status = game.status();
List<ScoreDto> scores = status.getStatus().entrySet().stream()
.map(ScoreDto::new)
Expand All @@ -44,9 +44,9 @@ public ResponseDto calculateScore() {
});
}

public ResponseDto changeState(String request) {
public ResponseDto changeState(String gameId, String request) {
return makeResponse(() -> {
GameEntity savedGameEntity = gameRepository.findById(DEFAULT_USER_ID)
GameEntity savedGameEntity = gameRepository.findById(gameId)
.orElseThrow(() -> new NoSuchElementException(NONE_ELEMENT_QUERY_RESULT_EXCEPTION_MESSAGE));
Game game = savedGameEntity.toDomain();
game = game.changeState(request);
Expand All @@ -56,9 +56,9 @@ public ResponseDto changeState(String request) {
});
}

public ResponseDto findAllPiecesOnBoard() {
public ResponseDto findAllPiecesOnBoard(String gameId) {
return makeResponse(() -> {
Game game = findGame();
Game game = findGame(gameId);
Board board = game.getBoard();

List<BoardDto> pieces = board.getPieces().entrySet().stream()
Expand All @@ -68,12 +68,12 @@ public ResponseDto findAllPiecesOnBoard() {
});
}

public ResponseDto move(PositionRequestDto positionRequestDTO) {
public ResponseDto move(String gameId, PositionRequestDto positionRequestDTO) {
return makeResponse(() -> {
Position from = Position.of(positionRequestDTO.getFrom());
Position to = Position.of(positionRequestDTO.getTo());

GameEntity saveEntity = gameRepository.findById(DEFAULT_USER_ID)
GameEntity saveEntity = gameRepository.findById(gameId)
.orElseThrow(() -> new NoSuchElementException(NONE_ELEMENT_QUERY_RESULT_EXCEPTION_MESSAGE));
Game game = saveEntity.toDomain();
game = game.move(from, to);
Expand All @@ -88,28 +88,40 @@ public ResponseDto move(PositionRequestDto positionRequestDTO) {
});
}

public ResponseDto getCurrentState() {
public ResponseDto getCurrentState(String gameId) {
return makeResponse(() -> {
Game game = findGame();
Game game = findGame(gameId);
return new ResponseDto(SUCCESS, GameDto.of(game.getTurn(), game.getStateType()));
});
}

public ResponseDto getWinner() {
public ResponseDto getWinner(String gameId) {
return makeResponse(() -> {
Game game = findGame();
Game game = findGame(gameId);
String winner = game.getWinner().name().toLowerCase();
return new ResponseDto(SUCCESS, winner);
});
}

public ResponseDto isNotFinish() {
public ResponseDto isNotFinish(String gameId) {
return makeResponse(() -> {
Game game = findGame();
Game game = findGame(gameId);
return new ResponseDto(SUCCESS, game.isNotFinished());
});
}

public ResponseDto findAllGameIds() {
return makeResponse(() -> new ResponseDto(SUCCESS, gameRepository.findAllIds()));
}

public ResponseDto createNewGame() {
return makeResponse(() -> {
GameEntity newGameEntity = GameEntity.of(READY_INSTANCE);
gameRepository.save(newGameEntity);
return new ResponseDto(SUCCESS, newGameEntity.getId());
});
}

private ResponseDto makeResponse(Supplier<ResponseDto> responseGenerator) {
try {
return responseGenerator.get();
Expand All @@ -118,8 +130,8 @@ private ResponseDto makeResponse(Supplier<ResponseDto> responseGenerator) {
}
}

private Game findGame() {
GameEntity gameEntity = gameRepository.findById(DEFAULT_USER_ID)
private Game findGame(String gameId) {
GameEntity gameEntity = gameRepository.findById(gameId)
.orElseThrow(() -> new NoSuchElementException(NONE_ELEMENT_QUERY_RESULT_EXCEPTION_MESSAGE));
return gameEntity.toDomain();
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/schema.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
create table if not exists game(
id bigint auto_increment,
id varchar(40),
state varchar(255) not null,
turn varchar(255) not null,
board varchar(255) not null,
Expand Down
Loading

0 comments on commit 89ec6d8

Please sign in to comment.