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

[사다리 미션] 황승준 미션 제출입니다. #23

Open
wants to merge 59 commits into
base: davidolleh
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
b07a49c
<FEAT> 기능 명세서 파일 추가
davidolleh Oct 30, 2024
f493a05
<FEAT> input, ouput view class 추가
davidolleh Oct 30, 2024
2254785
<FEAT> 연결 관련 enum class들 추가
davidolleh Oct 30, 2024
e0ffcfb
<FEAT> controller 객체 추가
davidolleh Oct 30, 2024
02b6a8d
<FEAT> line 객체 추가
davidolleh Oct 30, 2024
7cf4555
<FEAT> 참여자 객체 추가
davidolleh Oct 30, 2024
dcf7dc4
<FEAT> main 함수 추가
davidolleh Oct 30, 2024
06cc958
<FEAT> 당첨 객체 추가
davidolleh Oct 30, 2024
fc66931
<FEAT> 사다리 객체 추가
davidolleh Oct 30, 2024
2e22fee
<FEAT> 사다리 랜덤 생성 객체 추가
davidolleh Oct 30, 2024
613461c
<FIX> 이름 수정
davidolleh Oct 30, 2024
ed047ab
<FIX> 사다리 랜덤 생성 객체 추상화로 분리
davidolleh Oct 30, 2024
71d47c7
<FIX> nextInt 입력 받는거 nextLine으로 변경
davidolleh Oct 30, 2024
dd7174d
<FEAT> width, height ladder의 field로 추가
davidolleh Oct 30, 2024
5781a34
<FEAT> value object로 변경, 예외처리 추가
davidolleh Oct 30, 2024
9b5c7b5
<FEAT> 사다리 결과 출력 기능 추가
davidolleh Oct 30, 2024
125810f
<FEAT> Prize vo로 변경
davidolleh Oct 30, 2024
92408bb
<FEAT> 실행 결과 기능들 추가
davidolleh Oct 31, 2024
431bd39
<FEAT> 실행 결과 객체 추가
davidolleh Oct 31, 2024
77f88a7
<FEAT> controller 기능 추가
davidolleh Oct 31, 2024
9d693f0
<FEAT> Ladder 자동생성 테스트 추가
davidolleh Oct 31, 2024
91e4ceb
<FEAT> 기능 명세서 추가
davidolleh Oct 31, 2024
b70c3a5
<FIX> Indent 1로 마추려고 수정
davidolleh Oct 31, 2024
c76ef4a
<FIX> tmp 변수로 변경
davidolleh Oct 31, 2024
a09be2f
<FIX> 함수로 분리
davidolleh Oct 31, 2024
9bacca2
<FEAT> 개행문자 추가
davidolleh Oct 31, 2024
d767643
<FEAT> Person, Statistic 관련 test 추가
davidolleh Oct 31, 2024
6aef072
<FIX> warning 제거
davidolleh Oct 31, 2024
5402201
<FIX> 함수로 분리
davidolleh Oct 31, 2024
726700e
<FEAT> prize test 추가
davidolleh Oct 31, 2024
a2f5884
<FEAT> 기능명세서 기능 추가
davidolleh Oct 31, 2024
f567502
<FIX> warning 제거
davidolleh Oct 31, 2024
e278cc8
<REFACTOR> 1. Person 값 객체로 사용하지 않도록 수정, 2. 메서드 이름 동사형으로 수정
davidolleh Nov 12, 2024
bf26804
<REFACTOR> README 구체적으로 추가
davidolleh Nov 14, 2024
915c745
<REFACTOR> 변수 이름 수정
davidolleh Nov 14, 2024
d5eda95
<REFACTOR> 금액의 꽝에 대한 처리를 outputview의 역할로 수정
davidolleh Nov 14, 2024
6bf7754
<REFACTOR> Ladder 생성 로직과 entity 분리
davidolleh Nov 15, 2024
39d71d8
<REFACTOR> Line 이름 수정
davidolleh Nov 16, 2024
0c759b5
<REFACTOR> README 추가
davidolleh Nov 16, 2024
d67a2e9
<REFACTOR> line 특정 rowIndex의 방향 가져오는 함수 구현
davidolleh Nov 16, 2024
936a471
<REFACTOR> Ladder의 필드 RowLine으로 변경
davidolleh Nov 18, 2024
5aa5433
<REFACTOR> main class 이름 수정
davidolleh Nov 18, 2024
7057283
<REFACTOR> LadderGame 실행 구현
davidolleh Nov 18, 2024
d766f09
<REFACTOR> LadderGame 실행 구현
davidolleh Nov 18, 2024
f3dd305
<REFACTOR> Controller, OutputView LadderGame에 맞춰서 수정
davidolleh Nov 18, 2024
1d25eb1
<REFACTOR> 사용하지 않는 파일 삭제
davidolleh Nov 18, 2024
8f5d014
<REFACTOR> person record로 수정
davidolleh Nov 18, 2024
3268173
<REFACTOR> README 추가 작성
davidolleh Nov 18, 2024
19585d2
<REFACTOR> 불필요한 함서 제거
davidolleh Nov 18, 2024
afe1ed8
<REFACTOR> 필드 final로 변경
davidolleh Nov 18, 2024
a866afb
<REFACTOR> class record로 변경
davidolleh Nov 18, 2024
0c974c9
<REFACTOR> class record로 변경
davidolleh Nov 18, 2024
8bda0a9
<REFACTOR> LadderFactory 추상화
davidolleh Nov 18, 2024
4547ffe
<REFACTOR> 오타 수정
davidolleh Nov 20, 2024
7481d5d
<REFACTOR> 참여자 테스트 구현
davidolleh Nov 20, 2024
a08a3c9
<REFACTOR> 파일 삭제
davidolleh Nov 20, 2024
27da6f5
<REFACTOR> README 추가
davidolleh Nov 20, 2024
7e3f2e8
<REFACTOR> 테스트 구현
davidolleh Nov 20, 2024
81e327f
<REFACTOR> 정적 변수러 설정
davidolleh Nov 20, 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
43 changes: 43 additions & 0 deletions README.md

Choose a reason for hiding this comment

The 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,43 @@
# java-ladder

자바 사다리 미션 저장소

## 개요

참여자와 상품을 입력 받아 랜덤 사다리를 만들어 참여자와 상품을 연결시켜주는 게임이다.

## 요구사항

### 사람(Person)

- [x] 사람의 이름은 1자 이상 5자 이하여야 한다.

### 참여자(Participant)

- [x] 참여자들은 사다리에서 자신의 위치를 갖고 있다.
- [X] 참여자들은 정해진 라인을 따라 이동한다.

### 참여자들(Participants)

- [x] 참여자들의 이름은 중복이 될 수 없다.
- [x] 각 라인의 출발점에는 하나의 사람만 있을 수 있다.

### 상품(Prize)

- [x] 상품은 금액으로 이루어져 있다.
- [x] 상품의 금액이 값을 표현한다.(vo를 표현할 수 있는 말이 무엇이 있을까?)

### 라인(RowLine)

- [x] 라인들의 각 지점은 오른쪽, 왼쪽, 아래쪽 방향성 중 하나만을 가질 수 있다.
- [x] 라인이 연결성은 겹치지 않아야 한다.
- [x] 라인의 연결 여부는 랜덤으로 결정한다.

### 사다리(Ladder)

- [x] 여러개의 Line이 모여 하나의 사다리를 만든다.

### 사다리 게임(LadderGame)

- [x] 참여자들을 라인 따라 이동해 상품과 최종적으로 연결을 맺는다.
- [x] 게임이 완료되어야 최종 게임 결과를 확인할 수 있다.
Empty file removed src/main/java/.gitkeep
Empty file.
13 changes: 13 additions & 0 deletions src/main/java/LadderGameApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import view.InputView;
import view.OutputView;

public class LadderGameApplication {
public static void main(String[] args) {
LadderGameController ladderGameController = new LadderGameController(
new InputView(),
new OutputView()
);

ladderGameController.ladderGame();
}
}
94 changes: 94 additions & 0 deletions src/main/java/LadderGameController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import domain.*;
import view.InputView;
import view.OutputView;

import java.util.List;

public class LadderGameController {

private final InputView inputView;
private final OutputView outputView;

public LadderGameController(InputView inputView, OutputView outputView) {
this.inputView = inputView;
this.outputView = outputView;
}

public void ladderGame() {
List<Person> people = readParticipants();
List<Prize> prizes = readPrizes();

validateInputsCount(people.size(), prizes.size());

int height = readLadderHeight();
int width = people.size();

LadderFactory ladderGenerator = new RandomLadderFactory(height, width);
Ladder ladder = ladderGenerator.newInstance();

Participants participants = Participants.fromPeople(people);
LadderGame ladderGame = new LadderGame(participants, ladder, prizes);

outputView.printResult(ladderGame.getParticipants(), ladderGame.getLadder(), ladderGame.getPrizes());

ladderGame.start();

GameResult gameResult = ladderGame.getParticipantsPrizes();

printSpecificParticipantResult(ladderGame.getParticipants(), gameResult);

outputView.printParticipantsPrizesResult(ladderGame.getParticipants(), gameResult);
}

private List<Person> readParticipants() {
outputView.printParticipantInquiry();
List<Person> participants = inputView.readParticipants();
outputView.printEmptyLine();

return participants;
}

private List<Prize> readPrizes() {
outputView.printResultPrizeInquiry();
List<Prize> prizes = inputView.readPrizeResults();
outputView.printEmptyLine();

return prizes;
}

private int readLadderHeight() {
outputView.printLadderHeightInquiry();
int height = inputView.readLadderHeight();
outputView.printEmptyLine();

return height;
}

private String readParticipantName() {
outputView.printParticipantPrizeInquiry();
String name = inputView.readPersonName();
outputView.printEmptyLine();

return name;
}

private void printSpecificParticipantResult(Participants participants, GameResult gameResult) {
while (true) {
String name = readParticipantName();

if (name.equals("all")) {
break;
}

Person person = new Person(name);
Participant participant = participants.getParticipantByName(person);
outputView.printParticipantPrizeResult(gameResult.getPrize(participant));
}
}

private void validateInputsCount(int participantCount, int prizeCount) {
if (participantCount != prizeCount) {
throw new IllegalArgumentException("The number of participants does not match the number of prizes.");
}
}
}
6 changes: 6 additions & 0 deletions src/main/java/domain/Connection.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package domain;

public enum Connection {
CONNECTED,
UNCONNECTED,
}
Comment on lines +3 to +6

Choose a reason for hiding this comment

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

👍

Comment on lines +3 to +6

Choose a reason for hiding this comment

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

📝 Enum에 함수형 인터페이스 넣어보기 2

함수형 인터페이스를 필드로 선언해서, 각각의 enum마다 다음 동작을 정의할 수 있겠네요!

Suggested change
public enum Connection {
CONNECTED,
UNCONNECTED,
}
public enum Connection {
CONNECTED(Connection::createUnconnected),
UNCONNECTED(Connection::createRandomConnection),
;
private static final ThreadLocalRandom random = ThreadLocalRandom.current();
private static final int RANDOM_BOUND = 10;
private static final int THRESHOLD = 5;
final Supplier<Connection> createNext;
Connection(Supplier<Connection> createNext) {
this.createNext = createNext;
}
static Connection createRandomConnection() {
int randomValue = random.nextInt(RANDOM_BOUND);
if (randomValue < THRESHOLD) {
return Connection.CONNECTED;
}
return Connection.UNCONNECTED;
}
private static Connection createUnconnected() {
return UNCONNECTED;
}
public Connection createNext() {
return createNext.get();
}
}

11 changes: 11 additions & 0 deletions src/main/java/domain/Direction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package domain;

public enum Direction {
LEFT(-1), RIGHT(1), DOWN(0);

final int offset;

Direction(int offset) {
this.offset = offset;
}
Comment on lines +4 to +10

Choose a reason for hiding this comment

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

📝 Enum에 함수형 인터페이스 넣어보기 1

enum에도 메서드로 동작을 정의해볼 수 있을 것 같아요!!

Suggested change
LEFT(-1), RIGHT(1), DOWN(0);
final int offset;
Direction(int offset) {
this.offset = offset;
}
public enum Direction {
LEFT(-1),
RIGHT(1),
DOWN(0);
private final int offset;
Direction(int offset) {
this.offset = offset;
}
public int move(int position) {
return position + offset;
}

}
15 changes: 15 additions & 0 deletions src/main/java/domain/GameResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package domain;

import java.util.Map;

public class GameResult {
private final Map<Participant, Prize> gameResult;

public GameResult(Map<Participant, Prize> gameResult) {
this.gameResult = gameResult;
}

public Prize getPrize(Participant participant) {
return gameResult.get(participant);
}
}
7 changes: 7 additions & 0 deletions src/main/java/domain/GameState.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package domain;

public enum GameState {
READY,
PROGRESS,
FINISH,
}
15 changes: 15 additions & 0 deletions src/main/java/domain/Ladder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package domain;

Choose a reason for hiding this comment

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

domain을 기능별로 나누어서 여러 파일로 구현하셨네요!
저 같은 경우에는 파일 2개로 domain을 구현했는데, 이렇게 더 많이 나누는게 깔끔한 것 같아요.
참고하겠습니다.


import java.util.List;

public class Ladder {
private final List<RowLine> columnLines;

public Ladder(List<RowLine> columnLines) {
this.columnLines = columnLines;
}

public List<RowLine> getLines() {
return columnLines;
}
}
5 changes: 5 additions & 0 deletions src/main/java/domain/LadderFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package domain;

public interface LadderFactory {
Ladder newInstance();
}
84 changes: 84 additions & 0 deletions src/main/java/domain/LadderGame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package domain;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class LadderGame {
private final Participants participants;
private final Ladder ladder;
private final List<Prize> prizes;
private GameState gameState;
private Map<Integer, List<Integer>> result;

public LadderGame(Participants participants, Ladder ladder, List<Prize> prizes) {
this.participants = participants;
this.ladder = ladder;
this.prizes = prizes;
this.gameState = GameState.READY;
}

public void start() {
gameState = GameState.PROGRESS;

Map<Integer, List<Integer>> gameResult = new HashMap<>();

int participantsCount = participants.getParticipantsCount();

for (int i = 0; i < participantsCount; i++) {
Participant participant = participants.getParticipantByIndex(i);
Integer startPosition = participant.getPosition();
List<Integer> participantPositions = moveParticipant(participant);
gameResult.put(startPosition, participantPositions);
}

result = gameResult;

gameState = GameState.FINISH;
}

private List<Integer> moveParticipant(Participant participant) {
List<Integer> participantPositions = new ArrayList<>();

for (RowLine rowLine : ladder.getLines()) {
int currentPosition = participant.getPosition();
Direction direction = rowLine.getPositionDirection(currentPosition);

participant.move(direction);

participantPositions.add(participant.getPosition());
}

return participantPositions;
}

public GameResult getParticipantsPrizes() {
if (gameState != GameState.FINISH) {
throw new RuntimeException("게임이 진행중입니다!");
}

Map<Participant, Prize> participantsPrizes = new HashMap<>();

for (Integer startPosition : result.keySet()) {
List<Integer> positions = result.get(startPosition);
Integer lastPosition = positions.get(positions.size() - 1);

participantsPrizes.put(participants.getParticipantByIndex(startPosition), prizes.get(lastPosition));
}

return new GameResult(participantsPrizes);
}

public Participants getParticipants() {
return participants;
}

public Ladder getLadder() {
return ladder;
}

public List<Prize> getPrizes() {
return prizes;
}
}
38 changes: 38 additions & 0 deletions src/main/java/domain/Participant.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package domain;

import java.util.Objects;

public class Participant {
private final Person person;
private int position;

public Participant(Person person, int position) {
this.person = person;
this.position = position;
}

public void move(Direction direction) {
position = position + direction.offset;
}
Comment on lines +14 to +16

Choose a reason for hiding this comment

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

📝 Enum에 함수형 인터페이스 넣어보기 3

그럼 위에서 정의한 enum의 메서드로 특정 동작을 수행해서 position을 얻어낼 수 있겠어요

Suggested change
public void move(Direction direction) {
position = position + direction.offset;
}
public void move(Direction direction) {
this.position = direction.move(position);
}


public String getParticipantName() {
return person.name();
}

public int getPosition() {
return position;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Participant that = (Participant) o;
return Objects.equals(person.name(), that.person.name());
}

@Override
public int hashCode() {
return Objects.hashCode(person.name());
}
}
45 changes: 45 additions & 0 deletions src/main/java/domain/Participants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package domain;

import java.util.List;
import java.util.Set;
import java.util.stream.IntStream;

public record Participants(List<Participant> participants) {
public Participants {
validateParticipants(participants);
}

public static Participants fromPeople(List<Person> people) {
List<Participant> participants = IntStream.range(0, people.size())
.mapToObj(i -> new Participant(people.get(i), i))
.toList();

return new Participants(participants);
}

private void validateParticipants(List<Participant> participants) {
int participantsCount = participants.size();

Set<Participant> deduplicateParticipants = Set.copyOf(participants);
int deduplicateParticipantsCount = deduplicateParticipants.size();

if (participantsCount != deduplicateParticipantsCount) {
throw new IllegalArgumentException("중복된 이름의 참여자는 참여할 수 없습니다.");
}
}

public int getParticipantsCount() {
return participants.size();
}

public Participant getParticipantByIndex(int index) {
return participants.get(index);
}

public Participant getParticipantByName(Person person) {
return participants.stream()
.filter(participant -> participant.getParticipantName().equals(person.name()))
.findFirst()
.orElseThrow(IllegalArgumentException::new);
}
}
Loading