Skip to content

Commit

Permalink
[2단계 - 사다리 타기] 이든(최승준) 미션 제출합니다. (#366)
Browse files Browse the repository at this point in the history
* refactor : 클래스명이 의미를 더 잘 표현하도록 수정

* refactor : 오라클 자바 컨벤션에 맞도록 클래스 멤버 위치 조정

* refactor : 중복되는 네이밍 변경

generate -> generateBridge

* refactor : BridgeGeneratorStub 클래스, NPE 문제 방지

* remove : 입력 테스트 제거

* docs : Step2 기능 구현 문서 추가

* feat : 사다리 결과 출력 기능 구현

* refactor : 참가자 이름 입력 시, 구분자가 가장 마지막에 오는 경우 검증하도록 수정

* refactor : 패키지 구조 변경

* feat : 사다리 실행 결과 확인 기능 구현

* refactor : CustomException 제거

- 사용하는 이유가 따로 없기 때문에 RuntimeException 바로 상속받도록 변경

* refactor : 예외 메시지는 발생시키는 곳에서 관리하도록 변경

경# feat : 기능 추가

* refactor : 상수 네이밍 깔끔하게 변경

* refactor : 중복되는 bridge 랜덤 생성 로직 메서드 분리

* remove : 의미없는 상수 제거

* feat : 사용할 수 없는 이름 추가

* refactor : 재입력 메서드 네이밍 동일하게 변경(오버로딩)

* refactor : 커맨드 관련 상수 열거 클래스로 분리

PlayerName이 Command에 포함되는 text인지 검증하기 위해 Command Enum 생성

* refactor : 필드명으로 value 사용

* refactor : 불필요한 확장성을 위해 만든 RetryableController 삭제

* refactor : InputView에서만 사용되는 상수에 private 접근 제어 설정

* refactor : 코드라인 정리

* refactor : 코드 컨벤션에 맞춰 클래스 멤버 위치 조정

* refactor : ui 로직에 의존하던 LadderBridge enum 코드 제거

 outputView의 Map에서 bridgeMarker 관리

* refactor : Players 사다리 결과 형식 상수화

"실행 결과"와 같이 의미하는 바가 확실한 일반 문자열은 따로 상수화해주지 않아도 알아보기 편하지만 "%d %s" 등과 같은 format은 이름없이 존재하면 의미를 파악하기 어렵기 때문에 상수화를 통해 관리

* docs : 사다리 종료 커멘드 관련 문서 수정

* remove : LadderBridge getter 삭제

* refactor : 오라클 컨벤션에 맞게 멤버 위치 변경

* refactor : 테스트 클래스 위치, 네이밍 수정

* refactor : 테스트 내부 클래스로 분리

* refactor : 중복 로직 메서드 분리

* refactor : final 키워드 사용해서 재할당 불가능하게 수정

* refactor : final 키워드 사용해서 재할당 불가능하게 수정

* refactor : 직관적인 에러 메시지 네이밍 사용

* refactor : ealry return 적용하여 else 키워드 제거

* refactor : Ladder의 책임 분리

현재와 같이 설계하면 같은 사다리에 다른 사람들과, 다른 결과들을 넣고싶다면 새로운 Ladder 객체를 생성해야 함
때문에 굳이 Ladder가 PlayerNames와 LadderResults를 알고 있어야한다는 책임을 주는 것보다 사다리 결과를 얻는 match 메서드에서 메서드 인자로 필요할 때 받아서 사용하는 것이 더 적합하다고 생각

* refactor : 한번에 index, name 조회해오도록 변경

* refactor : 클래스 변수, 인스턴스 변수 구분

* refactor : n번 조회 방식에서 단일 조회 방식으로 변경

* refactor : OS 별로 다른 이스케이프 문자 고려하여 코드 수정
  • Loading branch information
PgmJun authored Mar 1, 2024
1 parent 140bc88 commit 2073642
Show file tree
Hide file tree
Showing 40 changed files with 1,016 additions and 558 deletions.
60 changes: 58 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
## 기능 구현 사항
- [x] 참가자 이름 입력 기능
- [x] 콤마(,)로 구분해서 입력해야한다.
- [x] 이름에 공백이 붙어있으면 trim으로 공백을 제거한다.
- [x] 이름에 공백이 붙어있으면 replace()로 공백을 제거한다.
- [x] ⚠️ 이름 길이는 1 이상, 5 이하가 아니면 예외가 발생한다.
- [x] ⚠️ 공백 문자 입력 시, 예외가 발생한다.
- [ ] ⚠️ `all`,`fin` 이라는 이름 사용 시, 예외가 발생한다.

- [x] 실행 결과 입력 기능
- [x] 콤마(,)로 구분해서 입력해야한다.
- [x] 이름에 공백이 붙어있으면 replace()로 공백을 제거한다.
- [x] ⚠️ 길이가 1 이상, 5 이하가 아니면 예외가 발생한다.
- [x] ⚠️ 공백 문자 입력 시, 예외가 발생한다.
- [x] ⚠️ 참가자 이름의 수와 실행결과의 수가 다르면, 예외가 발생한다.

- [x] 사다리 높이 입력 기능
- [x] ⚠️ 정수형태가 아니면 예외가 발생한다.
Expand All @@ -12,17 +20,65 @@
- [x] 입력한 높이의 사다리 생성
- [x] |-----|-----| 모양과 같이 가로 라인이 겹치지 않도록 생성한다.

- [x] 결과 출력 기능
- [x] 사다리 실행 결과 출력 기능
- [x] 실행결과 메시지 출력
- [x] 참가자 이름 출력
- [x] 참가자 이름을 5자로 정의하고, 빈 칸이 생기면 공백으로 5자가 되도록 채운다.
- [x] 생성된 사다리를 출력
- [x] 실행 결과 출력

- [x] 사다리 실행 결과 확인 기능
- [x] 이름 입력
- [x] 단일 이름 입력 시, 단일 참가자의 결과 출력
- [x] `all` 입력 시, 전체 참가자의 결과 출력
- [x] ⚠️ 존재하지 않는 참가자 이름을 입력 시, 예외가 발생한다.
- [x] 해당하는 이름의 사다리 실행 결과 출력
- [x] `fin` 입력 시, 게임 종료

## 실행 결과
```
참여할 사람 이름을 입력하세요. (이름은 쉼표(,)로 구분하세요)
pobi,honux,crong,jk
실행 결과를 입력하세요. (결과는 쉼표(,)로 구분하세요)
꽝,5000,꽝,3000
최대 사다리 높이는 몇 개인가요?
5
사다리 결과
pobi honux crong jk
|-----| |-----|
| |-----| |
|-----| | |
| |-----| |
|-----| |-----|
꽝 5000 꽝 3000
결과를 보고 싶은 사람은?
pobi
실행 결과
결과를 보고 싶은 사람은?
all
실행 결과
pobi : 꽝
honux : 3000
crong : 꽝
jk : 5000
```


## 추가 구현 사항
- [x] Exception 발생 시, 오류 메시지 출력하고 해당 부분부터 재입력
- [x] 재입력 횟수가 10회 초과되면 예외가 발생되고 프로그램이 종료된다.
- [x] 참가자 인원은 2 이상, 10 이하여야한다.
- [x] 참가자 이름은 중복되지 않아야한다.
- [x] 사다리 실행 결과 입력 시, `fin`을 입력하면 게임이 종료된다.

## 프로그래밍 요구사항
- [x] indent(인덴트, 들여쓰기) depth를 2를 넘지 않도록 구현한다. 1까지만 허용한다.
Expand Down
16 changes: 11 additions & 5 deletions src/main/java/LadderGameApplication.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import controller.LadderController;
import domain.Ladder;
import domain.ladder.Ladder;
import domain.ladder.LadderHeight;
import domain.ladder.LadderResults;
import domain.player.PlayerNames;
import view.InputView;
import view.OutputView;

Expand All @@ -8,10 +11,13 @@
public class LadderGameApplication {

public static void main(String[] args) {
InputView inputView = new InputView(new Scanner(System.in));
OutputView outputView = new OutputView();
LadderController ladderController = new LadderController(inputView, outputView);
LadderController ladderController = new LadderController(new InputView(new Scanner(System.in)), new OutputView());

Ladder ladder = ladderController.createLadder();
PlayerNames playerNames = ladderController.readPlayerNames();
LadderResults results = ladderController.readLadderResults(playerNames.getCount());
LadderHeight ladderHeight = ladderController.readLadderHeight();

Ladder ladder = ladderController.createLadder(ladderHeight, playerNames, results);
ladderController.matchPlayerToResult(ladder, playerNames, results);
}
}
8 changes: 0 additions & 8 deletions src/main/java/common/exception/CustomException.java

This file was deleted.

36 changes: 0 additions & 36 deletions src/main/java/common/exception/message/ExceptionMessage.java

This file was deleted.

5 changes: 1 addition & 4 deletions src/main/java/common/exception/model/IOException.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package common.exception.model;

import common.exception.CustomException;

public class IOException extends CustomException {

public class IOException extends RuntimeException {
public IOException(String message) {
super(message);
}
Expand Down
5 changes: 1 addition & 4 deletions src/main/java/common/exception/model/NotFoundException.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package common.exception.model;

import common.exception.CustomException;

public class NotFoundException extends CustomException {

public class NotFoundException extends RuntimeException {
public NotFoundException(String message) {
super(message);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package common.exception.model;

import common.exception.CustomException;

public class ValidationException extends CustomException {

public class ValidationException extends RuntimeException {
public ValidationException(String message) {
super(message);
}
Expand Down
40 changes: 0 additions & 40 deletions src/main/java/controller/Controller.java

This file was deleted.

95 changes: 80 additions & 15 deletions src/main/java/controller/LadderController.java
Original file line number Diff line number Diff line change
@@ -1,45 +1,110 @@
package controller;

import domain.Ladder;
import domain.LadderHeight;
import domain.PlayerName;
import domain.PlayerNames;
import common.exception.model.IOException;
import domain.bridge.strategy.RandomBridgeGenerator;
import domain.ladder.Ladder;
import domain.ladder.LadderHeight;
import domain.ladder.LadderResults;
import domain.player.PlayerName;
import domain.player.PlayerNames;
import view.InputView;
import view.OutputView;
import view.command.Command;

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

public class LadderController extends Controller {
public class LadderController {
public static final int READ_LIMIT = 10;
public static final String READ_LIMIT_OVER = String.format("입력 횟수 제한(%d)를 초과하였습니다", READ_LIMIT);

private final InputView inputView;
private final OutputView outputView;
private int retryCount;

public LadderController(InputView inputView, OutputView outputView) {
super(inputView, outputView);
this.inputView = inputView;
this.outputView = outputView;
this.retryCount = 0;
}

public Ladder createLadder() {
PlayerNames playerNames = readPlayerNames();
LadderHeight ladderHeight = readLadderHeight();

Ladder ladder = Ladder.create(ladderHeight, playerNames, new RandomBridgeGenerator());
outputView.printLadder(playerNames, ladder);
public Ladder createLadder(final LadderHeight ladderHeight, final PlayerNames playerNames, final LadderResults results) {
Ladder ladder = Ladder.create(ladderHeight, playerNames.getCount(), new RandomBridgeGenerator());
outputView.printGeneratedLadder(ladder, playerNames, results);

return ladder;
}

private PlayerNames readPlayerNames() {
public PlayerNames readPlayerNames() {
return retry(() -> createPlayerNames(inputView.readPlayerNames()));
}

public PlayerNames createPlayerNames(String[] playerNamesInput) {
private PlayerNames createPlayerNames(final String[] playerNamesInput) {
List<PlayerName> playerNames = Arrays.stream(playerNamesInput)
.map(PlayerName::new)
.toList();

return new PlayerNames(playerNames);
}

private LadderHeight readLadderHeight() {
public LadderHeight readLadderHeight() {
return retry(() -> new LadderHeight(inputView.readLadderHeight()));
}

public LadderResults readLadderResults(final int playerCount) {
return retry(() -> new LadderResults(inputView.readLadderResults(), playerCount));
}

public void matchPlayerToResult(final Ladder ladder, final PlayerNames playerNames, final LadderResults results) {
retry(() -> findPlayerResult(ladder, playerNames, results));
outputView.printEndMessage();
}

private void findPlayerResult(final Ladder ladder, final PlayerNames playerNames, final LadderResults results) {
String inputPlayerName = inputView.readPlayerNameForGetResult();

while (!Command.isFinishCommand(inputPlayerName)) {
outputView.printPlayerLadderResult(getPlayerLadderResult(inputPlayerName, ladder, playerNames, results));
inputPlayerName = inputView.readPlayerNameForGetResult();
}
}

private Map<String, String> getPlayerLadderResult(final String inputPlayerName, final Ladder ladder,
final PlayerNames playerNames, final LadderResults results) {
if (Command.isAllCommand(inputPlayerName)) {
return ladder.findAllPlayersLadderResultValue(playerNames, results);
}
return ladder.findSinglePlayerLadderResultValue(inputPlayerName, playerNames, results);
}

<R> R retry(final Supplier<R> supplier) {
validateRetryCountLimit();
try {
R value = supplier.get();
retryCount = 0;
return value;
} catch (Exception exception) {
outputView.printErrorMessage(exception.getMessage());
return retry(supplier);
}
}

void retry(final Runnable runnable) {
validateRetryCountLimit();
try {
runnable.run();
retryCount = 0;
} catch (Exception exception) {
outputView.printErrorMessage(exception.getMessage());
retry(runnable);
}
}

private void validateRetryCountLimit() {
if (retryCount++ == READ_LIMIT) {
throw new IOException(READ_LIMIT_OVER);
}
}
}
34 changes: 0 additions & 34 deletions src/main/java/domain/Floor.java

This file was deleted.

Loading

0 comments on commit 2073642

Please sign in to comment.