-
Notifications
You must be signed in to change notification settings - Fork 0
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
base: main
Are you sure you want to change the base?
Changes from all commits
227e10f
479dd33
fa3f081
11d31ed
314f00d
6a0e142
95f6855
ca7c8d6
06abb19
ce71dda
1e63c66
ce96d76
6ba3533
39d4e46
1b31c3c
c4a600c
35f4996
068f395
578e675
06b0608
e886c52
a5de3c2
04bb0d8
7fada27
6fda343
f7d899e
3b99dd9
9cf0152
dcf1b6d
ea55c02
d46221c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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() | ||
} |
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(); | ||
} | ||
} |
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()); | ||
} | ||
} |
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); | ||
} | ||
} |
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); | ||
|
||
List<CarEntity> findByRacingGameId(Long id); | ||
} |
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 | ||
)); | ||
} | ||
} |
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(); | ||
} |
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() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이거 좋은데요 |
||
)); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package racingcar.dao.entity; | ||
|
||
public class CarEntity { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
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; | ||
} | ||
} |
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; | ||
} | ||
} |
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
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; | ||
} | ||
} |
There was a problem hiding this comment.
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>