diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..e72c072da --- /dev/null +++ b/.editorconfig @@ -0,0 +1,29 @@ +# top-most EditorConfig file +root = true + +[*] +# [encoding-utf8] +charset = utf-8 + +# [newline-lf] +end_of_line = lf + +# [newline-eof] +insert_final_newline = true + +[*.bat] +end_of_line = crlf + +[*.java] +# [indentation-tab] +indent_style = tab + +# [4-spaces-tab] +indent_size = 4 +tab_width = 4 + +# [no-trailing-spaces] +trim_trailing_whitespace = true + +[line-length-120] +max_line_length = 120 \ No newline at end of file diff --git a/README.md b/README.md index 1bee39036..63aca6312 100644 --- a/README.md +++ b/README.md @@ -1,130 +1,13 @@ -# 미션 - 숫자 야구 게임 - -## 🔍 진행방식 - -- 미션은 **기능 요구사항, 프로그래밍 요구사항, 과제 진행 요구사항** 세 가지로 구성되어 있다. -- 세 개의 요구사항을 만족하기 위해 노력한다. 특히 기능을 구현하기 전에 기능 목록을 만들고, 기능 단위로 커밋 하는 방식으로 진행한다. - -## ✉️ 미션 제출 방법 - -- 미션 구현을 완료한 후 GitHub을 통해 제출해야 한다. - - GitHub을 활용한 제출 방법은 [프리코스 과제 제출 문서](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse) 를 참고해 제출한다. -- GitHub에 미션을 제출한 후 [우아한테크코스 지원 플랫폼](https://apply.techcourse.co.kr) 에 접속하여 프리코스 과제를 제출한다. - - 자세한 방법은 [링크](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse#제출-가이드) 를 참고한다. - - **Pull Request만 보내고, 지원 플랫폼에서 과제를 제출하지 않으면 최종 제출하지 않은 것으로 처리되니 주의한다.** - -## ✔️ 과제 제출 전 체크리스트 - 0점 방지 - -- 터미널에서 `java -version`을 실행해 자바 8인지 확인한다. 또는 Eclipse, IntelliJ IDEA와 같은 IDE의 자바 8로 실행하는지 확인한다. -- 터미널에서 맥 또는 리눅스 사용자의 경우 `./gradlew clean test`, 윈도우 사용자의 경우 `gradlew.bat clean test` 명령을 실행했을 때 모든 테스트가 통과하는지 확인한다. - ---- - -## 🚀 기능 요구사항 - -기본적으로 1부터 9까지 서로 다른 수로 이루어진 3자리의 수를 맞추는 게임이다. - -- 같은 수가 같은 자리에 있으면 스트라이크, 다른 자리에 있으면 볼, 같은 수가 전혀 없으면 포볼 또는 낫싱이란 힌트를 얻고, 그 힌트를 이용해서 먼저 상대방(컴퓨터)의 수를 맞추면 승리한다. - - 예) 상대방(컴퓨터)의 수가 425일 때 - - 123을 제시한 경우 : 1스트라이크 - - 456을 제시한 경우 : 1볼 1스트라이크 - - 789를 제시한 경우 : 낫싱 -- 위 숫자 야구 게임에서 상대방의 역할을 컴퓨터가 한다. 컴퓨터는 1에서 9까지 서로 다른 임의의 수 3개를 선택한다. 게임 플레이어는 컴퓨터가 생각하고 있는 3개의 숫자를 입력하고, 컴퓨터는 입력한 숫자에 대한 결과를 출력한다. -- 이 같은 과정을 반복해 컴퓨터가 선택한 3개의 숫자를 모두 맞히면 게임이 종료된다. -- 게임을 종료한 후 게임을 다시 시작하거나 완전히 종료할 수 있다. -- 사용자가 잘못된 값을 입력할 경우 `IllegalArgumentException`을 발생시킨 후 애플리케이션은 종료되어야 한다. -- 아래의 프로그래밍 실행 결과 예시와 동일하게 입력과 출력이 이루어져야 한다. - -
- -## ✍🏻 입출력 요구사항 - -### ⌨️ 입력 - -- 3자리의 수 -- 게임이 끝난 경우 재시작/종료를 구분하는 1과 2 중 하나의 수 - -### 🖥 출력 - -- 입력한 수에 대한 결과를 볼, 스트라이크 개수로 표시 - -``` -1볼 1스트라이크 -``` - -- 하나도 없는 경우 - -``` -낫싱 -``` - -- 3개의 숫자를 모두 맞힐 경우 - -``` -3스트라이크 -3개의 숫자를 모두 맞히셨습니다! 게임 종료 -``` - -### 💻 프로그래밍 실행 결과 예시 - -``` -숫자를 입력해주세요 : 123 -1볼 1스트라이크 -숫자를 입력해주세요 : 145 -1볼 -숫자를 입력해주세요 : 671 -2볼 -숫자를 입력해주세요 : 216 -1스트라이크 -숫자를 입력해주세요 : 713 -3스트라이크 -3개의 숫자를 모두 맞히셨습니다! 게임 종료 -게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요. -1 -숫자를 입력해주세요 : 123 -1볼 -… -``` - -
- ---- - -## 🎱 프로그래밍 요구사항 - -- 프로그램을 실행하는 시작점은 `Application`의 `main()`이다. -- JDK 8 버전에서 실행 가능해야 한다. **JDK 8에서 정상 동작하지 않을 경우 0점 처리**한다. -- 자바 코드 컨벤션을 지키면서 프로그래밍한다. - - https://naver.github.io/hackday-conventions-java -- indent(인덴트, 들여쓰기) depth를 3이 넘지 않도록 구현한다. 2까지만 허용한다. - - 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다. - - 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메소드)를 분리하면 된다. -- 3항 연산자를 쓰지 않는다. -- 함수(또는 메소드)가 한 가지 일만 하도록 최대한 작게 만들어라. - -### 프로그래밍 요구사항 - Randoms, Console - -- JDK에서 기본 제공하는 Random, Scanner API 대신 `camp.nextstep.edu.missionutils`에서 제공하는 `Randoms`, `Console` API를 활용해 구현해야 한다. - - Random 값 추출은 `camp.nextstep.edu.missionutils.Randoms`의 `pickNumberInRange()`를 활용한다. - - 사용자가 입력하는 값은 `camp.nextstep.edu.missionutils.Console`의 `readLine()`을 활용한다. -- 프로그램 구현을 완료했을 때 `src/test/java` 디렉터리의 `ApplicationTest`에 있는 모든 테스트 케이스가 성공해야 한다. **테스트가 실패할 경우 0점 처리한다.** - -
- ---- - -## 📈 과제 진행 요구사항 - -- 미션은 [java-baseball-precourse](https://github.com/woowacourse/java-baseball-precourse) 저장소를 Fork/Clone해 시작한다. -- **기능을 구현하기 전에 java-baseball-precourse/README.md 파일에 구현할 기능 목록을 정리**해 추가한다. -- **Git의 커밋 단위는 앞 단계에서 README.md 파일에 정리한 기능 목록 단위**로 추가한다. - - [AngularJS Commit Message Conventions](https://gist.github.com/stephenparish/9941e89d80e2bc58a153) 참고해 commit log를 남긴다. -- 과제 진행 및 제출 방법은 [프리코스 과제 제출 문서](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse) 를 참고한다. - -
- ---- - -## 📝 License - -This project is [MIT](https://github.com/woowacourse/java-baseball-precourse/blob/master/LICENSE) licensed. +1. 랜덤으로 3가지 숫자 생성 + 1. 중복되지 안도록 + 2. 각 숫자가 1~9 범위 사이도록 +2. 입력받은 숫자 검증 + 1. 숫자 인지 + 2. 3자리인지 + 3. 각 자리수가 중복이 없는지 + 4. 각 자리수가 1~9 사이인지 +3. 숫자 평가 + 1. 볼인지 + 2. 스트라이큰지 + 3. 아무것도 없는지 +4. 게임 시작 diff --git a/build.gradle b/build.gradle index fae7297bd..746b9ede2 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,14 @@ +plugins { + id 'org.ec4j.editorconfig' version '0.0.3' + id 'checkstyle' + id 'java' +} + + apply plugin: 'java' apply plugin: 'eclipse' + version = '1.0.0' sourceCompatibility = 1.8 @@ -9,6 +17,22 @@ repositories { mavenCentral() } + +editorconfig { + excludes = ['build'] +} + +check.dependsOn editorconfigCheck + + +checkstyle { + maxWarnings = 0 + configFile = file("${rootDir}/naver-checkstyle-rules.xml") + configProperties = ["suppressionFile": "${rootDir}/naver-checkstyle-suppressions.xml"] + toolVersion = "10.3.4" +} + + dependencies { implementation('com.github.woowacourse-projects:mission-utils:1.0.0') } diff --git a/naver-checkstyle-rules.xml b/naver-checkstyle-rules.xml new file mode 100644 index 000000000..2b160504b --- /dev/null +++ b/naver-checkstyle-rules.xml @@ -0,0 +1,439 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/naver-checkstyle-suppressions.xml b/naver-checkstyle-suppressions.xml new file mode 100644 index 000000000..a24a100fa --- /dev/null +++ b/naver-checkstyle-suppressions.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/src/main/java/baseball/Application.java b/src/main/java/baseball/Application.java index 7f1901b8b..af92bd06c 100644 --- a/src/main/java/baseball/Application.java +++ b/src/main/java/baseball/Application.java @@ -1,7 +1,9 @@ package baseball; public class Application { - public static void main(String[] args) { - //TODO: 숫자 야구 게임 구현 - } + public static void main(String[] args) { + //TODO: 숫자 야구 게임 구현 + new BaseBallGame().play(); + + } } diff --git a/src/main/java/baseball/Ball.java b/src/main/java/baseball/Ball.java new file mode 100644 index 000000000..ebaa8c99f --- /dev/null +++ b/src/main/java/baseball/Ball.java @@ -0,0 +1,39 @@ +package baseball; + +public class Ball { + private final Integer number; + + public Ball(int number) { + validateRange(number); + this.number = number; + } + + public Ball(char ch) { + this(Integer.parseInt(String.valueOf(ch))); + } + + private void validateRange(int number) { + if (number < 1 || 9 < number) { + throw new IllegalArgumentException("공의 숫자는 1~9의 자연수만 가능합니다."); + } + } + + @Override + public boolean equals(Object obj) { + Ball ball = (Ball)obj; + return this.number.equals(ball.number); + } + + @Override + public int hashCode() { + if (number == null) { + return 0; + } + return number.hashCode(); + } + + @Override + public String toString() { + return this.number.toString(); + } +} diff --git a/src/main/java/baseball/Balls.java b/src/main/java/baseball/Balls.java new file mode 100644 index 000000000..4aded8323 --- /dev/null +++ b/src/main/java/baseball/Balls.java @@ -0,0 +1,73 @@ +package baseball; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import camp.nextstep.edu.missionutils.Randoms; + +public class Balls { + public static final int BALLS_COUNT = 3; + + private final List balls; + + public Balls(List balls) { + validate(balls); + this.balls = balls; + } + + public static Balls makeRandomBalls() { + List balls = new ArrayList<>(); + + while (balls.size() != BALLS_COUNT) { + Ball ball = new Ball(Randoms.pickNumberInRange(1, 9)); + + if (!balls.contains(ball)) { + balls.add(ball); + } + } + return new Balls(balls); + } + + public static Balls stringToBalls(String str) { + char[] chars = str.toCharArray(); + List balls = new ArrayList<>(); + + for (char ch : chars) { + balls.add(new Ball(ch)); + } + return new Balls(balls); + } + + private void validate(List balls) { + Set ballSet = new HashSet<>(balls); + if (ballSet.size() != BALLS_COUNT) { + throw new IllegalArgumentException("공의 숫자가 중복 됩니다."); + } + } + + public Ball get(int index) { + return balls.get(index); + } + + public boolean contains(Ball ball) { + return this.balls.contains(ball); + } + + @Override + public boolean equals(Object obj) { + Balls balls = (Balls)obj; + return this.balls.equals(balls.balls); + } + + @Override + public String toString() { + return Arrays.toString(this.balls.toArray()); + } + + public int getSize() { + return this.balls.size(); + } +} diff --git a/src/main/java/baseball/BaseBallGame.java b/src/main/java/baseball/BaseBallGame.java new file mode 100644 index 000000000..08da66432 --- /dev/null +++ b/src/main/java/baseball/BaseBallGame.java @@ -0,0 +1,93 @@ +package baseball; + +import static camp.nextstep.edu.missionutils.Console.*; + +public class BaseBallGame { + + private static final String CONTINUE = "1"; + private static final String QUIT = "2"; + + public BaseBallGame() { + } + + public void play() { + do { + game(); + } while (reGame()); + } + + public void game() { + Balls comBalls; + Result result; + comBalls = Balls.makeRandomBalls(); + do { + printUserInputMessage(); + result = Result.checkBalls(makeUserBalls(), comBalls); + printResult(result); + } while (!result.isAllStrikes()); + } + + private Balls makeUserBalls() { + Balls userBalls = null; + while (userBalls == null) { + String userInput = getUserInput(); + validateUserInput(userInput); + try { + userBalls = Balls.stringToBalls(userInput); + } catch (NumberFormatException e) { + printFormatExceptionMessage(); + } catch (Exception e) { + e.printStackTrace(); + } + } + return userBalls; + } + + private Boolean reGame() { + String input = ""; + while (invalidInput(input)) { + printCheckRestartMessage(); + input = getUserInput(); + } + printCheckRestartExceptionMessage(); + return input.equals(CONTINUE); + } + + private boolean invalidInput(String input) { + return !input.equals(CONTINUE) && !input.equals(QUIT); + } + + private void validateUserInput(String userInput) { + if (checkUserInputLength(userInput)) { + throw new IllegalArgumentException("입력값의 길이가 잘못 되었습니다."); + } + } + + private String getUserInput() { + return readLine(); + } + + private void printUserInputMessage() { + System.out.print("숫자를 입력해주세요 : "); + } + + private void printResult(Result result) { + System.out.println(result.getResultMessage()); + } + + private Boolean checkUserInputLength(String str) { + return str.length() != Balls.BALLS_COUNT; + } + + private void printFormatExceptionMessage() { + System.out.printf("%d개의 1~9 사이의 중복되지 않는 수만 입력할 수 있습니다.%n", Balls.BALLS_COUNT); + } + + private void printCheckRestartExceptionMessage() { + System.out.println("1, 2만 입력 가능합니다. 다시 입력해주세요."); + } + + private void printCheckRestartMessage() { + System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요."); + } +} diff --git a/src/main/java/baseball/Result.java b/src/main/java/baseball/Result.java new file mode 100644 index 000000000..36f39e166 --- /dev/null +++ b/src/main/java/baseball/Result.java @@ -0,0 +1,93 @@ +package baseball; + +import static baseball.Balls.*; + +public class Result { + + private static final String STRIKE = "스트라이크"; + private static final String BALL = "볼"; + private static final String NOTHING = "낫싱"; + + private final Integer strike; + private final Integer ball; + + public Result(Integer strike, Integer ball) { + this.strike = strike; + this.ball = ball; + } + + public static Result checkBalls(Balls gameBalls, Balls userBalls) { + int strike = 0; + int ball = 0; + + for (int i = 0; i < BALLS_COUNT; i++) { + Ball thisBall = gameBalls.get(i); + + if (thisBall.equals(userBalls.get(i))) { + strike++; + continue; + } + if (userBalls.contains(thisBall)) { + ball++; + } + } + + return new Result(strike, ball); + } + + public String getResultMessage() { + if (isNothing()) { + return NOTHING; + } + if (isStrike()) { + return strike + STRIKE; + } + if (isBall()) { + return ball + BALL; + } + return ball + BALL + " " + strike + STRIKE; + } + + public boolean isAllStrikes() { + if (strike == BALLS_COUNT) { + printEndMessage(); + return true; + } + return false; + } + + @Override + public boolean equals(Object obj) { + Result result = (Result)obj; + return compareStrikeAndBall(result); + } + + private boolean compareStrikeAndBall(Result result) { + return this.strike.equals(result.strike) && this.ball.equals(result.ball); + } + + private boolean isNothing() { + return strike == 0 && ball == 0; + } + + private boolean isStrike() { + return 0 < strike && ball == 0; + } + + private boolean isBall() { + return strike == 0 && 0 < ball; + } + + private boolean isStrikeAndBall() { + return 0 < strike && 0 < ball; + } + + private boolean isAllStrike() { + return strike == BALLS_COUNT; + } + + private void printEndMessage() { + System.out.printf("%d개의 숫자를 모두 맞히셨습니다! 게임 종료%n", BALLS_COUNT); + } + +} diff --git a/src/test/java/baseball/ApplicationTest.java b/src/test/java/baseball/ApplicationTest.java index 359aacfa4..cdc723d68 100644 --- a/src/test/java/baseball/ApplicationTest.java +++ b/src/test/java/baseball/ApplicationTest.java @@ -1,36 +1,35 @@ package baseball; -import camp.nextstep.edu.missionutils.test.NsTest; +import static camp.nextstep.edu.missionutils.test.Assertions.*; +import static org.assertj.core.api.Assertions.*; + import org.junit.jupiter.api.Test; -import static camp.nextstep.edu.missionutils.test.Assertions.assertRandomNumberInRangeTest; -import static camp.nextstep.edu.missionutils.test.Assertions.assertSimpleTest; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; +import camp.nextstep.edu.missionutils.test.NsTest; class ApplicationTest extends NsTest { - @Test - void 게임종료_후_재시작() { - assertRandomNumberInRangeTest( - () -> { - run("246", "135", "1", "597", "589", "2"); - assertThat(output()).contains("낫싱", "3스트라이크", "1볼 1스트라이크", "3스트라이크", "게임 종료"); - }, - 1, 3, 5, 5, 8, 9 - ); - } + @Test + void 게임종료_후_재시작() { + assertRandomNumberInRangeTest( + () -> { + run("246", "135", "1", "597", "589", "2"); + assertThat(output()).contains("낫싱", "3스트라이크", "1볼 1스트라이크", "3스트라이크", "게임 종료"); + }, + 1, 3, 5, 5, 8, 9 + ); + } - @Test - void 예외_테스트() { - assertSimpleTest(() -> - assertThatThrownBy(() -> runException("1234")) - .isInstanceOf(IllegalArgumentException.class) - ); - } + @Test + void 예외_테스트() { + assertSimpleTest(() -> + assertThatThrownBy(() -> runException("1234")) + .isInstanceOf(IllegalArgumentException.class) + ); + } - @Override - public void runMain() { - Application.main(new String[]{}); - } + @Override + public void runMain() { + Application.main(new String[] {}); + } } diff --git a/src/test/java/baseball/BallTest.java b/src/test/java/baseball/BallTest.java new file mode 100644 index 000000000..806f67c50 --- /dev/null +++ b/src/test/java/baseball/BallTest.java @@ -0,0 +1,31 @@ +package baseball; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +public class BallTest { + + @Test + public void smaller_ball() { + assertThrows(IllegalArgumentException.class, () -> new Ball(-1)); + } + + @Test + public void larger_ball() { + assertThrows(IllegalArgumentException.class, () -> new Ball(10)); + } + + @Test + public void nomal_ball() { + assertDoesNotThrow(() -> new Ball(1)); + assertDoesNotThrow(() -> new Ball(2)); + assertDoesNotThrow(() -> new Ball(3)); + assertDoesNotThrow(() -> new Ball(4)); + assertDoesNotThrow(() -> new Ball(5)); + assertDoesNotThrow(() -> new Ball(6)); + assertDoesNotThrow(() -> new Ball(7)); + assertDoesNotThrow(() -> new Ball(8)); + assertDoesNotThrow(() -> new Ball(9)); + } +} diff --git a/src/test/java/baseball/BallsTest.java b/src/test/java/baseball/BallsTest.java new file mode 100644 index 000000000..45f2f8c27 --- /dev/null +++ b/src/test/java/baseball/BallsTest.java @@ -0,0 +1,31 @@ +package baseball; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Test; + +public class BallsTest { + + public static Balls makeBalls(int... intArr) { + List ballList = new ArrayList<>(); + + for (int j : intArr) { + ballList.add(new Ball(j)); + } + return new Balls(ballList); + } + + @Test + public void checkBallsSize() { + // given + Balls balls = Balls.makeRandomBalls(); + + // when && then + assertEquals(balls.getSize(), Balls.BALLS_COUNT); + + } + +} diff --git a/src/test/java/baseball/ResultTest.java b/src/test/java/baseball/ResultTest.java new file mode 100644 index 000000000..d9f2bad20 --- /dev/null +++ b/src/test/java/baseball/ResultTest.java @@ -0,0 +1,87 @@ +package baseball; + +import static baseball.BallsTest.*; +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +public class ResultTest { + + @Test + void checkAllBallResult() { + // given + Balls userBalls = makeBalls(2, 3, 1); + Balls comBalls = makeBalls(1, 2, 3); + assertEquals(new Result(0, 3), + Result.checkBalls(comBalls, userBalls)); + } + + @Test + void checkAllStrikeResult() { + // given + Balls userBalls = makeBalls(1, 2, 3); + Balls comBalls = makeBalls(1, 2, 3); + assertEquals(new Result(3, 0), + Result.checkBalls(comBalls, userBalls)); + } + + @Test + void checkOneStrikeTwoBallResult() { + // given + Balls userBalls = makeBalls(1, 2, 3); + Balls comBalls = makeBalls(1, 3, 2); + assertEquals(new Result(1, 2), + Result.checkBalls(comBalls, userBalls)); + } + + @Test + void checkOneStrikeOneBallResult() { + // given + Balls userBalls = makeBalls(1, 2, 3); + Balls comBalls = makeBalls(1, 3, 4); + assertEquals(new Result(1, 1), + Result.checkBalls(comBalls, userBalls)); + } + + @Test + void checkNothingResult() { + // given + Balls userBalls = makeBalls(1, 2, 3); + Balls comBalls = makeBalls(4, 5, 6); + assertEquals(new Result(0, 0), + Result.checkBalls(comBalls, userBalls)); + } + + @Test + void checkStrikeMessage() { + int strike = 2; + int ball = 0; + assertEquals(new Result(strike, ball).getResultMessage(), + "2스트라이크"); + } + + @Test + void checkBallMessage() { + int strike = 0; + int ball = 2; + assertEquals(new Result(strike, ball).getResultMessage(), + "2볼"); + } + + @Test + void checkBallStrikeMessage() { + int strike = 1; + int ball = 2; + assertEquals(new Result(strike, ball).getResultMessage(), + "2볼 1스트라이크"); + } + + @Test + void checkNothingMessage() { + int strike = 0; + int ball = 0; + assertEquals(new Result(strike, ball).getResultMessage(), + "낫싱"); + } + +}