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

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

Merged
merged 7 commits into from
Apr 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions src/main/java/wooteco/chess/SparkChessApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

import wooteco.chess.controller.SparkChessController;
import wooteco.chess.repository.DataSource;
import wooteco.chess.repository.GameDAO;
import wooteco.chess.repository.GameDao;
import wooteco.chess.repository.MySQLDataSource;
import wooteco.chess.repository.jdbc.JDBCGameDAO;
import wooteco.chess.repository.jdbc.JDBCGameDao;
import wooteco.chess.repository.jdbc.JDBCTemplate;
import wooteco.chess.service.GameService;

Expand All @@ -15,7 +15,7 @@ public static void main(String[] args) {
port(8080);
staticFiles.location("/templates");
DataSource dataSource = new MySQLDataSource();
GameDAO gameDAO = new JDBCGameDAO(new JDBCTemplate(dataSource));
GameDao gameDAO = new JDBCGameDao(new JDBCTemplate(dataSource));
GameService gameService = new GameService(gameDAO);
SparkChessController controller = new SparkChessController(gameService);
controller.run();
Expand Down
26 changes: 13 additions & 13 deletions src/main/java/wooteco/chess/controller/SparkChessController.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
import spark.ModelAndView;
import spark.template.handlebars.HandlebarsTemplateEngine;
import wooteco.chess.service.GameService;
import wooteco.chess.view.dto.requestdto.PositionRequestDTO;
import wooteco.chess.view.response.StandardResponse;
import wooteco.chess.view.dto.requestdto.PositionRequestDto;
import wooteco.chess.view.response.ResponseDto;

public class SparkChessController {
private static final HandlebarsTemplateEngine TEMPLATE_ENGINE = new HandlebarsTemplateEngine();
private static final ModelAndView DEFAULT_MODEL_AND_VIEW = new ModelAndView(new HashMap<String, Object>(),
"index.html");
"index.hbs");

private final GameService gameService;

Expand All @@ -30,61 +30,61 @@ public void run() {

get("/chess/state", (req, res) ->
makeResponse(() ->
new StandardResponse(SUCCESS, toJsonTree(gameService.getCurrentState()))),
new ResponseDto(SUCCESS, toJsonTree(gameService.getCurrentState()))),
json()
);

post("/chess/state", (req, res) ->
makeResponse(() -> {
gameService.changeState(req.body());
return new StandardResponse(SUCCESS);
return new ResponseDto(SUCCESS);
}),
json()
);

get("/chess/pieces", (req, res) ->
makeResponse(() ->
new StandardResponse(SUCCESS, toJsonTree(this.gameService.findAllPiecesOnBoard()))
new ResponseDto(SUCCESS, toJsonTree(this.gameService.findAllPiecesOnBoard()))
),
json()
);

get("/chess/record", (req, res) ->
makeResponse(() ->
new StandardResponse(SUCCESS, toJsonTree(this.gameService.calculateScore()))
new ResponseDto(SUCCESS, toJsonTree(this.gameService.calculateScore()))
),
json()
);

post("/chess/move", (req, res) ->
makeResponse(() -> {
PositionRequestDTO requestDTO = fromJson(req.body(), PositionRequestDTO.class);
PositionRequestDto requestDTO = fromJson(req.body(), PositionRequestDto.class);
this.gameService.move(requestDTO);
return new StandardResponse(SUCCESS, toJsonTree(gameService.findChangedPiecesOnBoard(requestDTO)));
return new ResponseDto(SUCCESS, toJsonTree(gameService.findChangedPiecesOnBoard(requestDTO)));
}),
json()
);

get("/chess/isnotfinish", (req, res) ->
makeResponse(() ->
new StandardResponse(SUCCESS, toJsonTree(this.gameService.isNotFinish()))
new ResponseDto(SUCCESS, toJsonTree(this.gameService.isNotFinish()))
),
json()
);

get("/chess/result", (req, res) ->
makeResponse(() ->
new StandardResponse(SUCCESS, toJsonTree(this.gameService.getWinner()))
new ResponseDto(SUCCESS, toJsonTree(this.gameService.getWinner()))
),
json()
);
}

private StandardResponse makeResponse(Supplier<StandardResponse> responseGenerator) {
private ResponseDto makeResponse(Supplier<ResponseDto> responseGenerator) {
try {
return responseGenerator.get();
} catch (RuntimeException e) {
return new StandardResponse(ERROR, e.getMessage());
return new ResponseDto(ERROR, e.getMessage());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class ChessController {
public class SpringChessController {
@GetMapping("/")
Copy link

Choose a reason for hiding this comment

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

페이지를 render하는 컨트롤러와 API 호출 컨트롤러를 분리해 보는 것은 어떨까요?

/chess와 관련된 API를 분리한다면 해당 클래스 헤더에@RequestMapping('/chess')어노테이션으로 중복되는 URL명을 줄일 수 있을 것 같아요😀

public String index() {
return "index";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package wooteco.chess.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
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;
import wooteco.chess.view.response.ResponseDto;

@RestController
@RequestMapping("/chess")
public class SpringChessRestController {
private final GameService gameService;

public SpringChessRestController(GameService gameService) {
this.gameService = gameService;
}

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

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

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

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

@PostMapping("/move")
public ResponseDto move(@RequestBody PositionRequestDto requestDTO) {
return gameService.move(requestDTO);
}

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

@GetMapping("/result")
public ResponseDto findWinner() {
return gameService.getWinner();
}
}
3 changes: 3 additions & 0 deletions src/main/java/wooteco/chess/domain/board/BoardFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ 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 BoardFactory() {
}

public static Board create(String board) {
validateBoardRegex(Objects.requireNonNull(board));
Map<Position, Piece> pieces = BoardParser.parsePieces(board);
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/wooteco/chess/domain/board/BoardParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ public class BoardParser {
private static final String COLUMN_SEPARATOR = "";
private static final String EMPTY_ZONE = ".";

private BoardParser() {
}

public static Map<Position, Piece> parsePieces(String board) {
Map<Position, Piece> pieces = new HashMap<>();
String[] rowBoards = board.split(ROW_SEPARATOR);
Expand Down
9 changes: 2 additions & 7 deletions src/main/java/wooteco/chess/domain/game/Game.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package wooteco.chess.domain.game;

import static wooteco.chess.domain.piece.Team.*;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
Expand All @@ -17,6 +15,7 @@ public abstract class Game {
private static final Map<String, Function<Game, Game>> CHANGE_STATE_FUNCTIONS;
private static final String START_REQUEST = "start";
private static final String END_REQUEST = "end";
private static final int DEFAULT_GAME_ID = 1;

static {
CHANGE_STATE_FUNCTIONS = new HashMap<>();
Expand All @@ -28,12 +27,8 @@ public abstract class Game {
protected final Board board;
protected Team turn;

public Game(Board board) {
this(1, board, WHITE);
}

public Game(Board board, Team turn) {
this(1, board, turn);
this(DEFAULT_GAME_ID, board, turn);
}

public Game(int id, Board board, Team turn) {
Expand Down
7 changes: 4 additions & 3 deletions src/main/java/wooteco/chess/domain/piece/Empty.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@

public class Empty extends Piece {
public static final Empty EMPTY = new Empty();
private static final String INITIAL_CHARACTER = ".";

public Empty() {
super(NONE, ".");
private Empty() {
super(NONE, INITIAL_CHARACTER);
}

@Override
Expand All @@ -20,7 +21,7 @@ public List<Position> findMoveModeTrace(Position from, Position to) {

@Override
protected String getInitialCharacter() {
return ".";
return INITIAL_CHARACTER;
}

@Override
Expand Down
18 changes: 14 additions & 4 deletions src/main/java/wooteco/chess/domain/piece/Pawn.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

public class Pawn extends Piece {
private static final String INITIAL_CHARACTER = "P";
private static final int INITIAL_MAX_STEP = 2;
private static final int REVERSE_FACTOR = -1;
private static final int DEFAULT_STEP = 1;

public Pawn(Team team) {
super(team, INITIAL_CHARACTER);
Expand All @@ -18,7 +21,7 @@ public List<Position> findMoveModeTrace(Position from, Position to) {
throw new IllegalArgumentException("해당 위치로 이동할 수 없습니다.");
}

if ((Math.abs(to.getRankNumber() - from.getRankNumber()) == 2)) {
if ((Math.abs(to.getRankNumber() - from.getRankNumber()) == INITIAL_MAX_STEP)) {
return Position.findMultipleStepTrace(from, to);
}
return Collections.emptyList();
Expand All @@ -37,13 +40,20 @@ private boolean isNotMovable(Position start, Position end) {
}

private boolean isMovable(Position start, Position end) {
int rankMoveDistance = calculateMoveDistance(start, end);
return rankMoveDistance >= DEFAULT_STEP && rankMoveDistance <= INITIAL_MAX_STEP;
}

private int calculateMoveDistance(Position start, Position end) {
int rankMoveDistance = end.getRankNumber() - start.getRankNumber();
rankMoveDistance *= team.isBlack() ? -1 : 1;
return rankMoveDistance > 0 && rankMoveDistance <= 2;
if (team.isBlack()) {
return rankMoveDistance * REVERSE_FACTOR;
}
return rankMoveDistance;
}

private boolean isAbleToMoveDoubleSquare(Position start, Position end) {
return start.isInitialPawnPosition(team) || (Math.abs(end.getRankNumber() - start.getRankNumber()) != 2);
return start.isInitialPawnPosition(team) || (Math.abs(end.getRankNumber() - start.getRankNumber()) != INITIAL_MAX_STEP);
}

private boolean isNotAbleToMoveDoubleSquare(Position start, Position end) {
Expand Down
33 changes: 16 additions & 17 deletions src/main/java/wooteco/chess/domain/piece/PieceFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,33 @@
import static wooteco.chess.domain.piece.Team.*;

import java.util.Arrays;
import java.util.function.Supplier;

public enum PieceFactory {
BLACK_PAWN("P", () -> new Pawn(BLACK)),
BLACK_BISHOP("B", () -> new Bishop(BLACK)),
BLACK_KNIGHT("N", () -> new Knight(BLACK)),
BLACK_ROOK("R", () -> new Rook(BLACK)),
BLACK_QUEEN("Q", () -> new Queen(BLACK)),
BLACK_KING("K", () -> new King(BLACK)),
WHITE_PAWN("p", () -> new Pawn(WHITE)),
WHITE_BISHOP("b", () -> new Bishop(WHITE)),
WHITE_KNIGHT("n", () -> new Knight(WHITE)),
WHITE_ROOK("r", () -> new Rook(WHITE)),
WHITE_QUEEN("q", () -> new Queen(WHITE)),
WHITE_KING("k", () -> new King(WHITE));
BLACK_PAWN("P", new Pawn(BLACK)),
Copy link

Choose a reason for hiding this comment

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

피드백 반영 💯💯

BLACK_BISHOP("B", new Bishop(BLACK)),
BLACK_KNIGHT("N", new Knight(BLACK)),
BLACK_ROOK("R", new Rook(BLACK)),
BLACK_QUEEN("Q", new Queen(BLACK)),
BLACK_KING("K", new King(BLACK)),
WHITE_PAWN("p", new Pawn(WHITE)),
WHITE_BISHOP("b", new Bishop(WHITE)),
WHITE_KNIGHT("n", new Knight(WHITE)),
WHITE_ROOK("r", new Rook(WHITE)),
WHITE_QUEEN("q", new Queen(WHITE)),
WHITE_KING("k", new King(WHITE));

private final String symbol;
private final Supplier<Piece> pieceSupplier;
private final Piece piece;

PieceFactory(String symbol, Supplier<Piece> pieceSupplier) {
PieceFactory(String symbol, Piece piece) {
this.symbol = symbol;
this.pieceSupplier = pieceSupplier;
this.piece = piece;
}

public static Piece of(String symbol) {
return Arrays.stream(values())
.filter(val -> val.symbol.equals(symbol))
.map(val -> val.pieceSupplier.get())
.map(val -> val.piece)
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("유효한 심볼이 아닙니다. : " + symbol));
}
Expand Down
20 changes: 12 additions & 8 deletions src/main/java/wooteco/chess/domain/position/Position.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ public class Position {
private static final Map<String, Position> CACHE = new HashMap<>();

static {
initPositionCache();
for (int col = MIN_POSITION_NUMBER; col <= MAX_POSITION_NUMBER; col++) {
initColumnPositionCache(col);
}
}

private static void initPositionCache() {
for (int col = MIN_POSITION_NUMBER; col <= MAX_POSITION_NUMBER; col++) {
for (int row = MIN_POSITION_NUMBER; row <= MAX_POSITION_NUMBER; row++) {
CACHE.put(getKey(col, row), new Position(new Cell(col), new Cell(row)));
}
private static void initColumnPositionCache(int col) {
for (int row = MIN_POSITION_NUMBER; row <= MAX_POSITION_NUMBER; row++) {
CACHE.put(getKey(col, row), new Position(new Cell(col), new Cell(row)));
}
}

Expand All @@ -46,7 +46,11 @@ public static Position of(Cell file, Cell rank) {
}

private static String getKey(int file, int rank) {
return (char)('a' + file - 1) + String.valueOf(rank);
return convertColumnChar(file) + String.valueOf(rank);
}

private static char convertColumnChar(int file) {
return (char)('a' + file - 1);
}

public static List<Position> findMultipleStepTrace(Position from, Position to) {
Expand Down Expand Up @@ -100,6 +104,6 @@ public int getRankNumber() {

@Override
public String toString() {
return String.valueOf((char)('a' + col.getNumber() - 1)) + row.getNumber();
return String.valueOf(convertColumnChar(col.getNumber())) + row.getNumber();
}
}
Loading