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단계 #8

Open
wants to merge 31 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
227e10f
[1단계 - 웹 자동차 경주] 박스터(한우석) 미션 제출합니다. (#49)
drunkenhw Apr 14, 2023
479dd33
refactor: domain에서 spring 의존성 제거
drunkenhw Apr 14, 2023
fa3f081
refactor: save all 메서드 batch update로 변경
drunkenhw Apr 14, 2023
11d31ed
refactor: 불필요한 어노테이션 변경
drunkenhw Apr 14, 2023
314f00d
test: controller 단위 테스트 추가
drunkenhw Apr 14, 2023
6a0e142
test: display name 추가
drunkenhw Apr 14, 2023
95f6855
refactor: db접근을 위한 entity 추가
drunkenhw Apr 15, 2023
ca7c8d6
feat: 객체 검증 기능 추가
drunkenhw Apr 15, 2023
06abb19
refactor: racing game test 가독성 좋게 수정
drunkenhw Apr 15, 2023
ce71dda
refactor: 출력 형식에 맞도록 수정
drunkenhw Apr 15, 2023
1e63c66
refactor: racing game 방식 변경
drunkenhw Apr 15, 2023
ce96d76
refactor: 승자를 구하는 로직 추가
drunkenhw Apr 15, 2023
6ba3533
feat: racing game을 조회하는 기능 추가
drunkenhw Apr 16, 2023
39d4e46
feat: racing game id로 car를 조회하는 기능 추가
drunkenhw Apr 16, 2023
1b31c3c
feat: 전체 결과를 조회하여 결과를 반환하는 기능 추가
drunkenhw Apr 17, 2023
c4a600c
feat: api 추가
drunkenhw Apr 17, 2023
35f4996
feat: 예외 처리 컨트롤러 추가
drunkenhw Apr 17, 2023
068f395
feat: 콘솔 게임 기능 추가
drunkenhw Apr 17, 2023
578e675
feat: In memory Dao 추가
drunkenhw Apr 21, 2023
06b0608
refactor: simpleJdbcInsert를 사용하도록 변경
drunkenhw Apr 21, 2023
e886c52
refactor: 최상위 예외를 잡는 메서드 추가
drunkenhw Apr 21, 2023
a5de3c2
refactor: 프론트에서 List로 반환하도록 변경
drunkenhw Apr 23, 2023
04bb0d8
refactor: service 클래스 분리
drunkenhw Apr 23, 2023
7fada27
refactor: rest api 응답 형식으로 변경
drunkenhw Apr 23, 2023
6fda343
feat: valid를 통한 검증 추가
drunkenhw Apr 23, 2023
f7d899e
refactor: 결과를 조회하는 서비스에 transactional 추가
drunkenhw Apr 23, 2023
3b99dd9
refactor: 예외 처리 문구 수정
drunkenhw Apr 23, 2023
9cf0152
refactor: trasactional 어노테이션 추가
drunkenhw Apr 23, 2023
dcf1b6d
refactor: racing game을 수행하는 클래스 추가
drunkenhw Apr 23, 2023
ea55c02
refactor: racing game console 서비스 클래스 제거
drunkenhw Apr 26, 2023
d46221c
refactor: racing game play 서비스 클래스 제거
drunkenhw Apr 26, 2023
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
18 changes: 11 additions & 7 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.9'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id 'java'
id 'org.springframework.boot' version '2.7.9'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}

sourceCompatibility = '11'

repositories {
mavenCentral()
mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
runtimeOnly 'com.h2database:h2'
testImplementation 'io.rest-assured:rest-assured:4.4.0'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.springframework.boot:spring-boot-starter-validation'
}

tasks.named('test') {
useJUnitPlatform()
useJUnitPlatform()
}
10 changes: 10 additions & 0 deletions src/main/java/racingcar/RacingCarConsoleApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package racingcar;

import racingcar.controller.RacingGameConsoleController;

public class RacingCarConsoleApplication {
public static void main(String[] args) {
RacingGameConsoleController racingConsoleController = new RacingGameConsoleController();
racingConsoleController.run();
}
}
30 changes: 30 additions & 0 deletions src/main/java/racingcar/controller/ControllerAdvice.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package racingcar.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class ControllerAdvice {

@ExceptionHandler
public ResponseEntity<String> handleValidationExceptions(Exception e) {
return ResponseEntity.internalServerError().body("예상치 못한 오류가 발생했습니다");
}

@ExceptionHandler
public ResponseEntity<String> handleValidationExceptions(RuntimeException e) {
return ResponseEntity.internalServerError().body("예상치 못한 오류가 발생했습니다");
}

@ExceptionHandler
public ResponseEntity<String> handleValidationExceptions(IllegalArgumentException e) {
return ResponseEntity.badRequest().body(e.getMessage());
}

@ExceptionHandler
public ResponseEntity<String> handleValidationExceptions(MethodArgumentNotValidException e) {
return ResponseEntity.badRequest().body(e.getBindingResult().getFieldError().getDefaultMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package racingcar.controller;

import java.util.List;
import java.util.stream.Collectors;
import racingcar.domain.Car;
import racingcar.domain.Cars;
import racingcar.domain.RacingGame;
import racingcar.view.InputView;
import racingcar.view.OutputView;

public class RacingGameConsoleController {


public void run() {
List<String> names = InputView.inputNames();
int count = InputView.inputTryCount();

List<Car> cars = names.stream()
.map(Car::new)
.collect(Collectors.toList());
RacingGame racingGame = new RacingGame(count, new Cars(cars));
racingGame.run();

OutputView.printRacing(racingGame.getCars());
OutputView.printWinners(racingGame.findWinners());
}
}
37 changes: 37 additions & 0 deletions src/main/java/racingcar/controller/RacingGameWebController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package racingcar.controller;

import java.net.URI;
import java.util.List;
import org.springframework.http.ResponseEntity;
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.RestController;
import racingcar.dto.RacingGameRequest;
import racingcar.dto.RacingGameResponse;
import racingcar.service.RacingGameAddService;
import racingcar.service.RacingGameFindService;

@RestController
public class RacingGameWebController {
private final RacingGameAddService racingGameAddService;
private final RacingGameFindService racingGameFindService;

public RacingGameWebController(RacingGameAddService racingGameAddService,
RacingGameFindService racingGameFindService) {
this.racingGameAddService = racingGameAddService;
this.racingGameFindService = racingGameFindService;
}

@PostMapping("/plays")
public ResponseEntity<RacingGameResponse> play(@RequestBody RacingGameRequest racingGameRequest) {
RacingGameResponse racingGameResponse = racingGameAddService.addGame(racingGameRequest);
return ResponseEntity.created(URI.create("/plays/" + racingGameResponse.getGameId())).body(racingGameResponse);
}

@GetMapping("/plays")
public ResponseEntity<List<RacingGameResponse>> playHistory() {
List<RacingGameResponse> history = racingGameFindService.findHistory();
return ResponseEntity.ok(history);
}
}
11 changes: 11 additions & 0 deletions src/main/java/racingcar/dao/CarDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package racingcar.dao;

import java.util.List;
import racingcar.dao.entity.CarEntity;

public interface CarDao {

void saveAll(List<CarEntity> racingCars);

Choose a reason for hiding this comment

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

saveAll 이 void 이고, RacingGameDao 에서는 Long 이라서 통일성이 떨어지는 느낌
id를 반환할거면 다 똑같이 long 으로 적어줘
List<Long>


List<CarEntity> findByRacingGameId(Long id);
}
41 changes: 41 additions & 0 deletions src/main/java/racingcar/dao/CarJdbcDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package racingcar.dao;

import java.util.List;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.stereotype.Component;
import racingcar.dao.entity.CarEntity;

@Component
public class CarJdbcDao implements CarDao {

private final SimpleJdbcInsert simpleJdbcInsert;
private final JdbcTemplate jdbcTemplate;

public CarJdbcDao(JdbcTemplate jdbcTemplate) {
this.simpleJdbcInsert = new SimpleJdbcInsert(jdbcTemplate)
.withTableName("car")
.usingGeneratedKeyColumns("id");
this.jdbcTemplate = jdbcTemplate;
}

@Override
public void saveAll(List<CarEntity> racingCars) {
BeanPropertySqlParameterSource[] parameterSources = racingCars.stream()
.map(BeanPropertySqlParameterSource::new)
.toArray(BeanPropertySqlParameterSource[]::new);
simpleJdbcInsert.executeBatch(parameterSources);
}

@Override
public List<CarEntity> findByRacingGameId(Long racingGameId) {
return jdbcTemplate.query("SELECT * FROM car WHERE racing_game_id = " + racingGameId,
(resultSet, rowNum) -> new CarEntity(
resultSet.getString("name"),
resultSet.getInt("position"),
resultSet.getBoolean("winner"),
racingGameId
));
}
}
11 changes: 11 additions & 0 deletions src/main/java/racingcar/dao/RacingGameDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package racingcar.dao;

import java.util.List;
import racingcar.dao.entity.RacingGameEntity;

public interface RacingGameDao {

Long save(RacingGameEntity racingGameEntity);

List<RacingGameEntity> findAllByCreatedTimeAsc();
}
40 changes: 40 additions & 0 deletions src/main/java/racingcar/dao/RacingGameJdbcDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package racingcar.dao;

import java.util.List;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.stereotype.Component;
import racingcar.dao.entity.RacingGameEntity;

@Component
public class RacingGameJdbcDao implements RacingGameDao {

private final JdbcTemplate jdbcTemplate;
private final SimpleJdbcInsert simpleJdbcInsert;

public RacingGameJdbcDao(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
this.simpleJdbcInsert = new SimpleJdbcInsert(jdbcTemplate)
.withTableName("racing_game")
.usingGeneratedKeyColumns("id");
}

@Override
public Long save(RacingGameEntity racingGameEntity) {
SqlParameterSource params = new BeanPropertySqlParameterSource(racingGameEntity);
return simpleJdbcInsert.executeAndReturnKey(params).longValue();
}

@Override
public List<RacingGameEntity> findAllByCreatedTimeAsc() {
return jdbcTemplate.query(
"SELECT * FROM racing_game ORDER BY created_at DESC ",
(resultSet, rowNum) -> new RacingGameEntity(
resultSet.getLong("id"),
resultSet.getInt("trial_count"),
resultSet.getTimestamp("created_at").toLocalDateTime()

Choose a reason for hiding this comment

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

이거 좋은데요

));
}
}
32 changes: 32 additions & 0 deletions src/main/java/racingcar/dao/entity/CarEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package racingcar.dao.entity;

public class CarEntity {

Choose a reason for hiding this comment

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

Entity를 식별할 수 있는 식별자가 없는 것 같은데 의도하신걸까요? 🤔


private final String name;
private final int position;
private final boolean winner;
private final Long racingGameId;

public CarEntity(String name, int position, boolean isWin, Long gameId) {
this.name = name;
this.position = position;
this.winner = isWin;
this.racingGameId = gameId;
}

public String getName() {
return name;
}

public int getPosition() {
return position;
}

public boolean isWinner() {
return winner;
}

public Long getRacingGameId() {
return racingGameId;
}
}
32 changes: 32 additions & 0 deletions src/main/java/racingcar/dao/entity/RacingGameEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package racingcar.dao.entity;

import java.time.LocalDateTime;

public class RacingGameEntity {

private final Long id;
private final int trialCount;
private final LocalDateTime createdAt;

public RacingGameEntity(Long id, int trialCount, LocalDateTime createdTime) {
this.id = id;
this.trialCount = trialCount;
this.createdAt = createdTime;
}

public RacingGameEntity(int trialCount) {
this(null, trialCount, LocalDateTime.now());
}

public int getTrialCount() {
return trialCount;
}

public Long getId() {
return id;
}

public LocalDateTime getCreatedAt() {
return createdAt;
}
}
61 changes: 61 additions & 0 deletions src/main/java/racingcar/domain/Car.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package racingcar.domain;

public class Car {

private static final int MOVE_CONDITION = 4;
private static final int MAX_NAME_LENGTH = 5;

private final String name;
private int position = 0;

public Car(String name) {
validateName(name);
this.name = name;
}

private void validateName(String name) {
validateEmpty(name);
validateLength(name);
}

private void validateLength(String name) {
if (name.length() > MAX_NAME_LENGTH) {
throw new IllegalArgumentException("이름이 " + name.length() + "자 입니다. " + "이름은 5자 이하로 가능합니다.");
}
}
Comment on lines +21 to +25

Choose a reason for hiding this comment

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

이 부분은 name 쪽으로 가도 좋을지도?

private final Name name;


private void validateEmpty(String name) {
if (name == null || name.isBlank()) {
throw new IllegalArgumentException("이름은 공백일 수 없습니다.");
}
}

public void move(int number) {
if (number >= MOVE_CONDITION) {
addPosition();
}
}

private void addPosition() {
position++;
}

public boolean isDraw(Car other) {
return this.position == other.position;
}

public Car isWin(Car other) {
if (this.position > other.position) {
return this;
}
return other;
}

public int getPosition() {
return position;
}

public String getName() {
return name;
}
}
Loading