Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
559aa16
refactor: custom exception 제거
jongmee Feb 26, 2024
152a58e
refactor: view에서 사용되는 속성을 domain이 아닌 view에서 관리하기
jongmee Feb 26, 2024
7c3a3d3
docs: step2 구현 기능 목록 추가
jongmee Feb 26, 2024
5d73136
feat: 사다리 결과 입력 받는 기능 구현
jongmee Feb 26, 2024
0c60c4d
feat: 사다리 결과 도메인 클래스 생성
jongmee Feb 26, 2024
7cf44cb
refactor: 사다리 결과 관련 메서드 및 변수명 변경
jongmee Feb 26, 2024
23efef2
refactor: 생성자에서 list를 수정 불가하도록 변경
jongmee Feb 26, 2024
c189a12
test: 참가자의 현재 위치로 LadderStep 내에서 다음 위치를 찾는 메서드 테스트
jongmee Feb 26, 2024
9c0b7f3
feat: 참가자의 현재 위치로 LadderStep 내에서 다음 위치를 찾는 기능 구현
jongmee Feb 26, 2024
9529ded
refactor: 참가자 이름(String)을 포장하기
jongmee Feb 26, 2024
b88353f
test: 참가자 이름 테스트 클래스 변경
jongmee Feb 26, 2024
f14d3f7
test: 입력 순서대로 참가자의 사다리 위치를 설정하는 기능 테스트
jongmee Feb 26, 2024
5740e79
feat: 입력 순서대로 참가자의 사다리 위치를 설정하는 기능 구현
jongmee Feb 26, 2024
c66bb7a
refactor: 참가자 위치와 이름 관련 도메인 클래스명 변경
jongmee Feb 26, 2024
ddab37f
refactor: LadderStepGenerator 인터페이스 분리
jongmee Feb 26, 2024
a0f3a3f
test: 참가자의 시작 위치로 사다리를 타서 최종 위치를 구하는 기능 테스트
jongmee Feb 26, 2024
b50760a
feat: 참가자의 시작 위치로 사다리를 타서 최종 위치를 구하는 기능 구현
jongmee Feb 26, 2024
2152835
refactor: Pariticipant getter 반환 타입 변경
jongmee Feb 26, 2024
601dd30
test: 모든 참가자들이 순서대로 사다리를 실행하는 기능 테스트
jongmee Feb 26, 2024
1555ff6
feat: 모든 참가자들이 순서대로 사다리를 실행하는 기능 구현
jongmee Feb 26, 2024
2e37a87
refactor: 불변 객체인 Position을 record로 변경
jongmee Feb 26, 2024
d77cd9b
feat: controller에서 사다리 결과 입력 받기
jongmee Feb 26, 2024
c86b963
feat: 사다리 실행 결과 출력 구현
jongmee Feb 27, 2024
d38d6f1
refactor: LadderGameResult 객체를 result 패키지에서 관리
jongmee Feb 27, 2024
aec2bf9
test: 개인별 사다리 타기 결과 산출 기능 테스트
jongmee Feb 27, 2024
afedbd6
feat: 개인별 사다리 타기 결과 산출 기능 구현
jongmee Feb 27, 2024
010c323
refactor: PersonalResult 도메인 클래스명 변경
jongmee Feb 27, 2024
5e0d192
refactor: 사다리 실행 결과 도메인 클래스명 LadderGamePrize로 변경
jongmee Feb 27, 2024
6a1b42a
refactor: 참가자별 게임 결과 속성명 변경
jongmee Feb 27, 2024
9520ea9
test: 참가자 이름으로 사다리 실행 결과를 조회하는 기능 테스트
jongmee Feb 27, 2024
3234aa2
feat: 참가자 이름으로 사다리 실행 결과를 조회하는 기능 구현
jongmee Feb 27, 2024
ef2d39a
refactor: 게임 결과 조회 반환값 변경
jongmee Feb 27, 2024
0424ff7
feat: 모든 참가자의 게임 결과를 조회하는 getter 생성
jongmee Feb 27, 2024
da240bd
refactor: 참가자들의 게임 결과를 구하는 메서드 반환값 변경
jongmee Feb 27, 2024
a5fbd73
refactor: OutputView 메서드 순서 변경
jongmee Feb 27, 2024
8dd6600
feat: 사다리 게임 결과 출력 구현
jongmee Feb 27, 2024
e0c83e7
refactor: GameResults의 getter 이름 변경
jongmee Feb 27, 2024
9db9345
fix: 존재하지 않는 참가자 이름으로 결과 조회시 재입력 받기
jongmee Feb 27, 2024
55306a1
refactor: 클래스 간 의존성을 주입해주는 manager 클래스 삭제
jongmee Feb 27, 2024
f0cd254
refactor: Position 도메인 클래스 삭제
jongmee Feb 27, 2024
b33f9d4
refactor: Ladder 클래스의 사다리 실행 메서드명 변경
jongmee Feb 27, 2024
11a1f72
refactor: List를 Set으로 변환할 때 copyOf 대신 HashSet 생성자 사용
jongmee Feb 27, 2024
00543c0
refactor: 사다리 게임 결과를 담는 list를 변경 불가능하도록 수정
jongmee Feb 27, 2024
3ee5b31
refactor: 지역 변수명 변경
jongmee Feb 27, 2024
efabfc2
refactor: 인터페이스를 구현하는 메서드에 오버라이드 애너테이션 추가
jongmee Feb 28, 2024
713963a
refactor: 참가자들의 게임 결과를 Map<String, String>으로 저장하기
jongmee Feb 29, 2024
f45737b
test: 참가자들의 사다리 게임 실행 테스트 이름 변경
jongmee Feb 29, 2024
d276102
refactor: 참가자의 위치(position)를 Participants에서 Map으로 관리
jongmee Feb 29, 2024
89ff18b
refactor: 참가자의 이름을 포장하지 않고 String 으로 관리
jongmee Feb 29, 2024
6001dc8
chore: 변수명 오타 수정
jongmee Feb 29, 2024
f986172
refactor: Entry type을 var로 대체
jongmee Feb 29, 2024
2ed7f54
refactor: run() 내부 메서드 및 변수 호출 순서 변경
jongmee Feb 29, 2024
aa3b4f5
refactor: 사다리 게임 결과 계산하는 메서드 이름 변경
jongmee Feb 29, 2024
6475887
style: 코드 공백 포맷팅
jongmee Feb 29, 2024
7a45c30
refactor: 불필요한 Optional 객체 생성 제거
jongmee Feb 29, 2024
7921897
refactor: ExceptionHandler에서 불필요한 Optional 제거
jongmee Mar 1, 2024
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
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@
2. 입력 받은 사다리 높이에 해당하는 사다리를 생성한다.
1. 각 사다리 높이마다 참가자 수만큼 사다리 발판(`—----`) 유무를 결정한다.
2. 사다리 발판은 이웃할 수 없다. (`|-----|-----|`)
3. 사다리 타기를 진행한다.
1. 입력된 참가자 순서대로 사다리를 탄다.
2. 한 계단씩 내려가며 좌우에 발판이 있는지 확인한다.
3. 발판이 있는 쪽으로 이동한다.
4. 마지막 계단까지 마치면 해당 참가자의 결과를 저장한다.
4. 사다리 타기 어플리케이션을 종료한다.
1. `all` 이 입력되면 종료한다.

## 입출력 기능

Expand All @@ -14,12 +21,18 @@
1. 사람 이름 목록을 입력한다.
1. 사람 이름을 쉼표(,)를 기준으로 구분한다.
2. 최대 5글자의 알파벳으로 이루어진 이름을 가진다.
2. 사다리 높이를 입력한다.
2. 실행 결과를 입력한다.
1. 참여할 사람 수만큼 입력한다.
3. 사다리 높이를 입력한다.
1. 1 이상이다.

### 출력

1. 사다리를 출력한다.
1. 참가자 이름의 순서는 입력된 순서로 출력한다.
2. 각 참가자 이름은 6자의 길이로 출력한다.
2. 각 참가자 이름은 5자의 길이로 출력한다.
3. 참가자 이름과 사다리 세로선(`|`)은 오른쪽 정렬된다.
4. 하단에 사다리 결과를 입력된 순서로 출력한다.
2. 사다리를 탄 결과를 출력한다.
1. 참가자 이름을 입력한 경우, 해당 참가자의 결과를 출력한다.
2. `all` 을 입력한 경우, 모든 참가자의 결과를 출력한다.
4 changes: 1 addition & 3 deletions src/main/java/ladder/Application.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package ladder;

import ladder.controller.LadderGame;
import ladder.manager.LadderGameManager;

public class Application {
public static void main(String[] args) {
LadderGameManager ladderGameManager = new LadderGameManager();
LadderGame ladderGame = ladderGameManager.createLadderGame();
LadderGame ladderGame = new LadderGame();
ladderGame.run();
}
}
62 changes: 47 additions & 15 deletions src/main/java/ladder/controller/LadderGame.java
Original file line number Diff line number Diff line change
@@ -1,33 +1,37 @@
package ladder.controller;

import ladder.domain.generator.LadderStepGenerator;
import ladder.domain.generator.RandomLadderStepGenerator;
import ladder.domain.ladder.Height;
import ladder.domain.ladder.Ladder;
import ladder.domain.result.GameResults;
import ladder.domain.result.LadderGamePrize;
import ladder.domain.participant.Participants;
import ladder.exception.ExceptionHandler;
import ladder.view.InputView;
import ladder.view.OutputView;

import java.util.List;
import java.util.Objects;

public class LadderGame {
private final InputView inputView;
private final OutputView outputView;
private final ExceptionHandler exceptionHandler;
private static final String FINISH_COMMAND = "all";

public LadderGame(
final InputView inputView,
final OutputView outputView,
final ExceptionHandler exceptionHandler) {
this.inputView = inputView;
this.outputView = outputView;
this.exceptionHandler = exceptionHandler;
}
private final InputView inputView = new InputView();
private final OutputView outputView = new OutputView();
private final ExceptionHandler exceptionHandler = new ExceptionHandler(outputView);

public void run() {
final Participants participants = exceptionHandler.retryOnException(this::createParticipants);
final LadderGamePrize ladderGamePrize = exceptionHandler.retryOnException(this::readLadderGameResult);
final int width = participants.getNecessaryLadderWidth();
final Ladder ladder = createLadder(width);
printLadder(participants, ladder);
participants.playAll(ladder);
final GameResults gameResults = ladderGamePrize.calculdateGameResults(participants);

printLadder(participants, ladder, ladderGamePrize);
printGameResult(gameResults);

inputView.closeResource();
}

Expand All @@ -38,17 +42,45 @@ private Participants createParticipants() {

private Ladder createLadder(final int stepWidth) {
final Height height = exceptionHandler.retryOnException(this::readLadderHeight);
return new Ladder(height, stepWidth);
final LadderStepGenerator ladderStepGenerator = new RandomLadderStepGenerator();
return new Ladder(height, stepWidth, ladderStepGenerator);
}

private LadderGamePrize readLadderGameResult() {
final List<String> ladderGameResult = inputView.readLadderGameResult();
return new LadderGamePrize(ladderGameResult);
}

private Height readLadderHeight() {
final int ladderHeight = inputView.readLadderHeight();
return new Height(ladderHeight);
}

private void printLadder(final Participants participants, final Ladder ladder) {
outputView.printResultPrefix();
private void printLadder(
final Participants participants,
final Ladder ladder,
final LadderGamePrize ladderGamePrize) {
outputView.printLadderPrefix();
outputView.printParticipants(participants);
outputView.printLadder(ladder);
outputView.printLadderGamePrize(ladderGamePrize);
}

private void printGameResult(final GameResults gameResults) {
boolean retry = true;
while (retry) {
retry = exceptionHandler.retryOnException(() -> printGameResultByCommand(gameResults));
}
}

private boolean printGameResultByCommand(final GameResults gameResults) {
final String gameResultTarget = inputView.readGameResultTarget();
if (Objects.equals(gameResultTarget, FINISH_COMMAND)) {
outputView.printAllGameResults(gameResults);
return false;
}
final String personalGameResult = gameResults.findByName(gameResultTarget);
outputView.printPersonalGameResult(personalGameResult);
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ladder.domain.generator;

import ladder.domain.ladder.LadderStep;

public interface LadderStepGenerator {
LadderStep generate(final int stepWidth);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
import java.util.List;
import java.util.Random;

public class RandomLadderStepGenerator {
public class RandomLadderStepGenerator implements LadderStepGenerator {
private static final Random random = new Random();

static public LadderStep generate(final int stepWidth) {
@Override
public LadderStep generate(final int stepWidth) {
final List<Path> ladderPaths = new ArrayList<>();
while (ladderPaths.size() < stepWidth) {
final Path currentPath = generatePath();
Expand All @@ -19,7 +20,7 @@ static public LadderStep generate(final int stepWidth) {
return new LadderStep(ladderPaths);
}

static private Path generatePath() {
private Path generatePath() {
final boolean isAvailable = random.nextBoolean();
return Path.from(isAvailable);
}
Expand Down
6 changes: 1 addition & 5 deletions src/main/java/ladder/domain/ladder/Height.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package ladder.domain.ladder;

import ladder.exception.ladder.InvalidHeightRangeException;

import java.util.List;

public class Height {
private static final int MIN_HEIGHT = 1;

Expand All @@ -16,7 +12,7 @@ public Height(final int value) {

private void validateHeightRange(final int value) {
if (value < MIN_HEIGHT) {
throw new InvalidHeightRangeException();
throw new IllegalArgumentException("사다리 높이는 1 이상의 정수입니다.");
}
}

Expand Down
28 changes: 22 additions & 6 deletions src/main/java/ladder/domain/ladder/Ladder.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package ladder.domain.ladder;

import ladder.domain.generator.RandomLadderStepGenerator;
import ladder.domain.generator.LadderStepGenerator;

import java.util.ArrayList;
import java.util.List;
Expand All @@ -10,20 +10,36 @@
public class Ladder {
private final List<LadderStep> ladderSteps;

public Ladder(final Height height, final int stepWidth) {
this.ladderSteps = generateLadderSteps(height, stepWidth);
public Ladder(
final Height height,
final int stepWidth,
final LadderStepGenerator ladderStepGenerator) {
final List<LadderStep> generatedLadderSteps = generateLadderSteps(height, stepWidth, ladderStepGenerator);
this.ladderSteps = unmodifiableList(generatedLadderSteps);
}

private List<LadderStep> generateLadderSteps(final Height height, final int stepWidth) {
private List<LadderStep> generateLadderSteps(
final Height height,
final int stepWidth,
final LadderStepGenerator ladderStepGenerator) {
final List<LadderStep> ladderSteps = new ArrayList<>();
while (height.isGreaterThan(ladderSteps.size())) {
final LadderStep currentLadderStep = RandomLadderStepGenerator.generate(stepWidth);
final LadderStep currentLadderStep = ladderStepGenerator.generate(stepWidth);
ladderSteps.add(currentLadderStep);
}
return ladderSteps;
}

public int playFrom(int startPosition) {
int nextPosition = -1;
for (LadderStep step : ladderSteps) {
nextPosition = step.findNextPosition(startPosition);
startPosition = nextPosition;
}
return nextPosition;
}

public List<LadderStep> getLadderSteps() {
return unmodifiableList(ladderSteps);
return ladderSteps;
}
}
17 changes: 15 additions & 2 deletions src/main/java/ladder/domain/ladder/LadderStep.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public LadderStep(List<Path> ladderPaths) {
private List<Path> correctLadderPaths(List<Path> ladderPaths) {
final List<Path> correctedLadderPaths = new ArrayList<>();
Path prevPath = EMPTY;
for (Path currentPath: ladderPaths) {
for (Path currentPath : ladderPaths) {
final Path correctedPath = correctPath(prevPath, currentPath);
correctedLadderPaths.add(correctedPath);
prevPath = correctedPath;
Expand All @@ -26,12 +26,25 @@ private List<Path> correctLadderPaths(List<Path> ladderPaths) {
}

private Path correctPath(final Path prevPath, final Path currentPath) {
if(prevPath.equals(EMPTY)) {
if (prevPath.equals(EMPTY)) {
return currentPath;
}
return EMPTY;
}

public int findNextPosition(final int position) {
if (position > 0 && isExistIn(position - 1)) {
return position - 1;
} else if (position < ladderPaths.size() && isExistIn(position)) {
return position + 1;
}
return position;
}

private boolean isExistIn(final int position) {
return ladderPaths.get(position).isExist();
}

public List<Path> getLadderPaths() {
return ladderPaths;
}
Expand Down
14 changes: 2 additions & 12 deletions src/main/java/ladder/domain/ladder/Path.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
package ladder.domain.ladder;

public enum Path {
EMPTY(" "),
EXIST("-----");

private final String shape;

Path(final String shape) {
this.shape = shape;
}
EMPTY,
EXIST;

public static Path from(final boolean isAvailable) {
if (isAvailable) {
Expand All @@ -20,8 +14,4 @@ public static Path from(final boolean isAvailable) {
public boolean isExist() {
return this.equals(EXIST);
}

public String getShape() {
return shape;
}
}
14 changes: 5 additions & 9 deletions src/main/java/ladder/domain/participant/Participant.java
Original file line number Diff line number Diff line change
@@ -1,30 +1,26 @@
package ladder.domain.participant;

import ladder.exception.participant.InvalidNameLengthException;
import ladder.exception.participant.NonAlphabeticNameException;

public class Participant {
private static final int MAX_NAME_LENGTH = 5;
private static final String NAME_REGEX = "^[a-zA-Z]*$";

private final String name;

public Participant(String name) {
name = name.trim();
public Participant(final String name) {
validateNameLength(name);
validateIsAlphabetic(name);
validateAlphabeticName(name);
this.name = name;
}

private void validateNameLength(final String name) {
if (name.isEmpty() || name.length() > MAX_NAME_LENGTH) {
throw new InvalidNameLengthException();
throw new IllegalArgumentException("이름은 1에서 5자 사이로 입력해 주세요.");
}
}

private static void validateIsAlphabetic(final String name) {
private void validateAlphabeticName(final String name) {
if (!name.matches(NAME_REGEX)) {
throw new NonAlphabeticNameException();
throw new IllegalArgumentException("이름은 영어로 입력해 주세요.");
}
}

Expand Down
Loading