diff --git a/src/main/java/.gitkeep b/src/main/java/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/LadderApplication.java b/src/main/java/LadderApplication.java new file mode 100644 index 0000000..b1c7e09 --- /dev/null +++ b/src/main/java/LadderApplication.java @@ -0,0 +1,23 @@ +import controller.LadderController; +import repository.ladder.LadderRepository; +import repository.results.ResultsRepository; +import repository.users.UserRepository; +import service.ladder.LadderServiceImpl; +import service.results.ResultsServiceImpl; +import service.users.UserService; +import view.InputView; +import view.OutputView; + +public class LadderApplication { + public static void main(String[] args) { + LadderController ladderController = new LadderController( + new LadderServiceImpl(new LadderRepository()), + new UserService(new UserRepository()), + new ResultsServiceImpl(new ResultsRepository()), + new OutputView(), + new InputView() + ); + + ladderController.start(); + } +} diff --git a/src/main/java/controller/LadderController.java b/src/main/java/controller/LadderController.java new file mode 100644 index 0000000..2e2972c --- /dev/null +++ b/src/main/java/controller/LadderController.java @@ -0,0 +1,78 @@ +package controller; + +import domain.ladder.Ladder; +import domain.ladder.LadderLine; +import domain.results.Results; +import domain.users.User; +import domain.users.Users; +import service.ladder.LadderService; +import service.results.ResultsService; +import service.users.UserService; +import view.InputView; +import view.OutputView; + +public class LadderController { + + private final LadderService ladderService; + private final UserService userService; + private final ResultsService resultsService; + private final OutputView outputView; + private final InputView inputView; + + public LadderController(final LadderService ladderService, final UserService userService, final ResultsService resultsService, final OutputView outputView, final InputView inputView) { + this.ladderService = ladderService; + this.userService = userService; + this.resultsService = resultsService; + this.outputView = outputView; + this.inputView = inputView; + } + + public void start() { + userService.makeUsers(inputView.inputUserNames()); + resultsService.saveResults(inputView.inputResults()); + ladderService.makeLadder(userService.getUsers().users().size(), inputView.inputHeight()); + + userService.updatePosition(ladderService.getLadder(), userService.getUsers()); + + printLadder(userService.getUsers(), ladderService.getLadder(), resultsService.getResults()); + printLadderResult(userService.getUsers(), resultsService.getResults()); + } + + private void printLadder(final Users users, final Ladder ladder, final Results results) { + for (User user : users.users()) { + outputView.printUser(user.getName()); + } + outputView.printEmpty(); + for (LadderLine ladderLine : ladder.ladderLines()) { + outputView.printLadderLine(ladderLine.connections()); + } + for (String result : results.results()) { + outputView.printResult(result); + } + outputView.printEmpty(); + } + + private void printLadderResult(final Users users, final Results results) { + int printCount = 0; + while (printCount < users.users().size()) { + final String wantedUserName = inputView.inputWantedUserName(); + printResult(wantedUserName, users, results, wantedUserName.equals("all")); + } + } + + private void printResult(final String wantedUserName, final Users users, final Results results, final boolean isAll) { + if (!isAll) { + outputView.printExecutionResult(); + outputView.printUserResult(results.results() + .get(userService.findByName(wantedUserName).getPosition()) + ); + return; + } + + outputView.printExecutionResult(); + for (User user : users.users()) { + outputView.printAllUserResults(user.getName(), results.results() + .get(user.getPosition())); + } + } +} diff --git a/src/main/java/domain/ladder/Ladder.java b/src/main/java/domain/ladder/Ladder.java new file mode 100644 index 0000000..00eec49 --- /dev/null +++ b/src/main/java/domain/ladder/Ladder.java @@ -0,0 +1,9 @@ +package domain.ladder; + +import java.util.List; + +public record Ladder( + List ladderLines, + LadderInfo ladderInfo +) { +} diff --git a/src/main/java/domain/ladder/LadderInfo.java b/src/main/java/domain/ladder/LadderInfo.java new file mode 100644 index 0000000..e6018fc --- /dev/null +++ b/src/main/java/domain/ladder/LadderInfo.java @@ -0,0 +1,7 @@ +package domain.ladder; + +public record LadderInfo( + int width, + int height +) { +} diff --git a/src/main/java/domain/ladder/LadderLine.java b/src/main/java/domain/ladder/LadderLine.java new file mode 100644 index 0000000..a59f859 --- /dev/null +++ b/src/main/java/domain/ladder/LadderLine.java @@ -0,0 +1,8 @@ +package domain.ladder; + +import java.util.List; + +public record LadderLine( + List connections +) { +} diff --git a/src/main/java/domain/ladder/LadderLineConnection.java b/src/main/java/domain/ladder/LadderLineConnection.java new file mode 100644 index 0000000..a848022 --- /dev/null +++ b/src/main/java/domain/ladder/LadderLineConnection.java @@ -0,0 +1,28 @@ +package domain.ladder; + +import java.util.Arrays; + +public enum LadderLineConnection { + + CONNECT_LADDER("|-----", true), + NOT_CONNECT_LADDER("| ", false); + + LadderLineConnection(final String ladderConnectionFormat, final boolean isConnected) { + this.ladderConnectionFormat = ladderConnectionFormat; + this.isConnected = isConnected; + } + + private final String ladderConnectionFormat; + private final boolean isConnected; + + public String getLadderConnectionFormat() { + return ladderConnectionFormat; + } + + public static LadderLineConnection of(final boolean isConnected) { + if (isConnected) { + return CONNECT_LADDER; + } + return NOT_CONNECT_LADDER; + } +} diff --git a/src/main/java/domain/results/Results.java b/src/main/java/domain/results/Results.java new file mode 100644 index 0000000..6eeaf4b --- /dev/null +++ b/src/main/java/domain/results/Results.java @@ -0,0 +1,9 @@ +package domain.results; + +import java.util.List; + +public record Results( + List results +) { + +} diff --git a/src/main/java/domain/users/User.java b/src/main/java/domain/users/User.java new file mode 100644 index 0000000..937de0f --- /dev/null +++ b/src/main/java/domain/users/User.java @@ -0,0 +1,25 @@ +package domain.users; + +public class User { + + private final String name; + private int position; + + public User(final String name, final int position) { + this.name = name; + this.position = position; + } + + public String getName() { + return name; + } + + public void setPosition(int position) { + this.position = position; + } + + public int getPosition() { + return position; + } + +} diff --git a/src/main/java/domain/users/Users.java b/src/main/java/domain/users/Users.java new file mode 100644 index 0000000..1a68e63 --- /dev/null +++ b/src/main/java/domain/users/Users.java @@ -0,0 +1,8 @@ +package domain.users; + +import java.util.List; + +public record Users( + List users +) { +} diff --git a/src/main/java/repository/ladder/LadderRepository.java b/src/main/java/repository/ladder/LadderRepository.java new file mode 100644 index 0000000..b755d05 --- /dev/null +++ b/src/main/java/repository/ladder/LadderRepository.java @@ -0,0 +1,16 @@ +package repository.ladder; + +import domain.ladder.Ladder; + +public class LadderRepository { + + private Ladder ladder; + + public Ladder getLadder() { + return ladder; + } + + public void setLadder(final Ladder ladder) { + this.ladder = ladder; + } +} diff --git a/src/main/java/repository/results/ResultsRepository.java b/src/main/java/repository/results/ResultsRepository.java new file mode 100644 index 0000000..ad57597 --- /dev/null +++ b/src/main/java/repository/results/ResultsRepository.java @@ -0,0 +1,16 @@ +package repository.results; + +import domain.results.Results; + +public class ResultsRepository { + + private Results results; + + public Results getResults() { + return results; + } + + public void setResults(final Results results) { + this.results = results; + } +} diff --git a/src/main/java/repository/users/UserRepository.java b/src/main/java/repository/users/UserRepository.java new file mode 100644 index 0000000..24cc56d --- /dev/null +++ b/src/main/java/repository/users/UserRepository.java @@ -0,0 +1,25 @@ +package repository.users; + +import domain.users.User; +import domain.users.Users; + +public class UserRepository { + + private Users users; + + public Users getUsers() { + return users; + } + + public void setUsers(final Users users) { + this.users = users; + } + + public User findByName(final String userName) { + return users.users().stream() + .filter(user -> user.getName().equals(userName)) + .findFirst() + .orElseThrow(() -> new RuntimeException("해당 유저를 찾을 수 없습니다!")); // 또는 예외를 던질 수 있습니다. + } + +} diff --git a/src/main/java/service/ladder/LadderService.java b/src/main/java/service/ladder/LadderService.java new file mode 100644 index 0000000..b7fb07f --- /dev/null +++ b/src/main/java/service/ladder/LadderService.java @@ -0,0 +1,10 @@ +package service.ladder; + +import domain.ladder.Ladder; + +public interface LadderService { + + void makeLadder(final int width, final int height); + + Ladder getLadder(); +} diff --git a/src/main/java/service/ladder/LadderServiceImpl.java b/src/main/java/service/ladder/LadderServiceImpl.java new file mode 100644 index 0000000..e2afd44 --- /dev/null +++ b/src/main/java/service/ladder/LadderServiceImpl.java @@ -0,0 +1,58 @@ +package service.ladder; + +import domain.ladder.Ladder; +import domain.ladder.LadderInfo; +import domain.ladder.LadderLine; +import repository.ladder.LadderRepository; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.stream.IntStream; + +public class LadderServiceImpl implements LadderService { + + private final LadderRepository ladderRepository; + + public LadderServiceImpl(final LadderRepository ladderRepository) { + this.ladderRepository = ladderRepository; + } + + @Override + public void makeLadder(final int width, final int height) { + ladderRepository.setLadder(new Ladder(makeLadderLines(height, width), new LadderInfo(width, height))); + } + + private List makeLadderLines(final int height, final int width) { + return IntStream.range(0, height) + .mapToObj(i -> makeLadderLine(width)) + .toList(); + } + + private LadderLine makeLadderLine(final int width) { + List connections = makeConnections(width); + return new LadderLine(connections); + } + + private List makeConnections(final int width) { + List connections = new ArrayList(); + Random random = new Random(); + + while (connections.size() < width - 1) { + addConnections(connections, random.nextBoolean()); + } + + return connections; + } + + private void addConnections(final List connections, final boolean isConnected) { + if (connections.isEmpty() || !isConnected || !connections.get(connections.size() - 1)) { + connections.add(isConnected); + } + } + + @Override + public Ladder getLadder() { + return ladderRepository.getLadder(); + } +} diff --git a/src/main/java/service/results/ResultsService.java b/src/main/java/service/results/ResultsService.java new file mode 100644 index 0000000..078ffff --- /dev/null +++ b/src/main/java/service/results/ResultsService.java @@ -0,0 +1,11 @@ +package service.results; + +import domain.results.Results; + +import java.util.List; + +public interface ResultsService { + void saveResults(final List results); + + Results getResults(); +} diff --git a/src/main/java/service/results/ResultsServiceImpl.java b/src/main/java/service/results/ResultsServiceImpl.java new file mode 100644 index 0000000..26d5743 --- /dev/null +++ b/src/main/java/service/results/ResultsServiceImpl.java @@ -0,0 +1,25 @@ +package service.results; + +import domain.results.Results; +import repository.results.ResultsRepository; + +import java.util.List; + +public class ResultsServiceImpl implements ResultsService { + + private final ResultsRepository resultsRepository; + + public ResultsServiceImpl(final ResultsRepository resultsRepository) { + this.resultsRepository = resultsRepository; + } + + @Override + public void saveResults(final List results) { + resultsRepository.setResults(new Results(results)); + } + + @Override + public Results getResults() { + return resultsRepository.getResults(); + } +} diff --git a/src/main/java/service/users/UserService.java b/src/main/java/service/users/UserService.java new file mode 100644 index 0000000..beeac63 --- /dev/null +++ b/src/main/java/service/users/UserService.java @@ -0,0 +1,76 @@ +package service.users; + +import domain.ladder.Ladder; +import domain.ladder.LadderInfo; +import domain.ladder.LadderLine; +import domain.users.User; +import domain.users.Users; +import repository.users.UserRepository; + +import java.util.List; + +public class UserService { + + private final UserRepository userRepository; + + public UserService(UserRepository userRepository) { + this.userRepository = userRepository; + } + + public void makeUsers(final List userNames) { + userRepository.setUsers(new Users(userNames.stream() + .map(userName -> new User(userName, userNames.indexOf(userName))) + .toList())); + } + + public void updatePosition(final Ladder ladder, final Users users) { + for (User user : users.users()) { + updatePosition(user, ladder.ladderLines(), ladder.ladderInfo()); + } + } + + public Users getUsers() { + return userRepository.getUsers(); + } + + public User findByName(final String name) { + return userRepository.findByName(name); + } + + private void updatePosition(final User user, final List ladderLines, final LadderInfo ladderInfo) { + for (LadderLine ladderLine : ladderLines) { + final boolean isConnectedRight = checkRightConnection(ladderLine.connections(), user.getPosition(), ladderInfo.width()); + final boolean isConnectedLeft = checkLeftConnection(ladderLine.connections(), user.getPosition()); + decideMoving(isConnectedLeft, isConnectedRight, user); + } + } + + private boolean checkRightConnection(final List connections, final int position, final int width) { + if (position == width - 1) { + return false; + } + return connections.get(position); + } + + private boolean checkLeftConnection(final List connections, final int position) { + if (position - 1 < 0) { + return false; + } + return connections.get(position - 1); + } + + private void decideMoving(final boolean isConnectedLeft, final boolean isConnectedRight, final User user) { + if (!isConnectedLeft && !isConnectedRight) { + return; + } + decideMovingLeftOrRight(isConnectedLeft, user); + } + + private void decideMovingLeftOrRight(final boolean isConnectedLeft, final User user) { + if (isConnectedLeft) { + user.setPosition(user.getPosition() - 1); + return; + } + user.setPosition(user.getPosition() + 1); + } +} diff --git a/src/main/java/util/TextUtils.java b/src/main/java/util/TextUtils.java new file mode 100644 index 0000000..8cbea75 --- /dev/null +++ b/src/main/java/util/TextUtils.java @@ -0,0 +1,13 @@ +package util; + +import java.util.ArrayList; +import java.util.List; + +public class TextUtils { + + private static final String SPLIT_CHARACTERS = ","; + + public static List splitMessageWithComma(final String message) { + return new ArrayList(List.of(message.split(SPLIT_CHARACTERS))); + } +} diff --git a/src/main/java/view/InputView.java b/src/main/java/view/InputView.java new file mode 100644 index 0000000..e8c303d --- /dev/null +++ b/src/main/java/view/InputView.java @@ -0,0 +1,31 @@ +package view; + +import util.TextUtils; + +import java.util.List; +import java.util.Scanner; + +public class InputView { + + private final Scanner scanner = new Scanner(System.in); + + public List inputUserNames() { + System.out.println("참여할 사람 이름을 입력하세요. (이름은 쉼표(,)로 구분하세요)"); + return TextUtils.splitMessageWithComma(scanner.nextLine()); + } + + public List inputResults() { + System.out.println("실행 결과를 입력하세요. (결과는 쉼표(,)로 구분하세요)"); + return TextUtils.splitMessageWithComma(scanner.nextLine()); + } + + public int inputHeight() { + System.out.println("최대 사다리의 높이는 몇 개인가요?"); + return scanner.nextInt(); + } + + public String inputWantedUserName() { + System.out.println("결과를 보고 싶은 사람은?"); + return scanner.next(); + } +} diff --git a/src/main/java/view/OutputView.java b/src/main/java/view/OutputView.java new file mode 100644 index 0000000..b641ce9 --- /dev/null +++ b/src/main/java/view/OutputView.java @@ -0,0 +1,42 @@ +package view; + +import domain.ladder.LadderLineConnection; + +import java.util.List; + +public class OutputView { + + private static final String EDGE_OF_LADDER = "|"; + + public void printEmpty() { + System.out.println(" "); + } + + public void printUser(final String userName) { + System.out.print(userName + " "); + } + + public void printResult(final String result) { + System.out.print(result + " "); + } + + public void printLadderLine(final List connections) { + final List line = connections.stream() + .map(connection -> LadderLineConnection.of(connection).getLadderConnectionFormat()) + .toList(); + System.out.println(String.join("", line) + EDGE_OF_LADDER); + } + + public void printUserResult(final String result) { + System.out.println(result); + System.out.println(" "); + } + + public void printAllUserResults(final String name, final String result) { + System.out.println(name + " : " + result); + } + + public void printExecutionResult() { + System.out.println("실행 결과"); + } +} diff --git a/src/test/java/.gitkeep b/src/test/java/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/java/ladder/LadderLineConnectionTest.java b/src/test/java/ladder/LadderLineConnectionTest.java new file mode 100644 index 0000000..2ebdd6f --- /dev/null +++ b/src/test/java/ladder/LadderLineConnectionTest.java @@ -0,0 +1,27 @@ +package ladder; + +import domain.ladder.LadderLineConnection; +import org.junit.jupiter.api.*; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@DisplayName("사다리 연결 테스트") +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +public class LadderLineConnectionTest { + + @Test + @DisplayName("연결 유무에 따라 사다리의 모양이 바뀐다.") + public void 연결_유무에_따라_사다리의_모양이_바뀐다() { + //given + final String expected1 = "|-----"; + final String expected2 = "| "; + final boolean isConnected1 = true; + final boolean isConnected2 = false; + + //when, then + Assertions.assertAll( + () -> assertEquals(LadderLineConnection.of(isConnected1).getLadderConnectionFormat(), expected1), + () -> assertEquals(LadderLineConnection.of(isConnected2).getLadderConnectionFormat(), expected2) + ); + } +}