From 671f06b78db5027ca8fdcddd0c2123d7218ff953 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Thu, 9 Nov 2023 17:09:18 +0900 Subject: [PATCH 01/92] =?UTF-8?q?fix=20:=20kotest=20markTime=20=EC=9D=B4?= =?UTF-8?q?=EC=8A=88=20=ED=95=B4=EA=B2=B0=EC=9D=84=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?=EB=B2=84=EC=A0=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index e78e729567..5588be3c32 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,7 +13,7 @@ repositories { dependencies { testImplementation("org.junit.jupiter", "junit-jupiter", "5.8.2") testImplementation("org.assertj", "assertj-core", "3.22.0") - testImplementation("io.kotest", "kotest-runner-junit5", "5.2.3") + testImplementation("io.kotest", "kotest-runner-junit5", "5.4.0") } tasks { From f9a331c682a6ec4b2b7579e7a60adecbff169bc4 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Thu, 9 Nov 2023 23:38:31 +0900 Subject: [PATCH 02/92] =?UTF-8?q?feat=20:=20=EB=AC=B8=EC=9E=90=EC=97=B4=20?= =?UTF-8?q?=EC=8B=9D=20=EB=8F=84=EB=A9=94=EC=9D=B8=20(=20Expression=20)=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/domain/expression/Expression.kt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/main/kotlin/camp/nextstep/edu/step/domain/expression/Expression.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/domain/expression/Expression.kt b/src/main/kotlin/camp/nextstep/edu/step/domain/expression/Expression.kt new file mode 100644 index 0000000000..55aa9bc0b8 --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/domain/expression/Expression.kt @@ -0,0 +1,18 @@ +package camp.nextstep.edu.step.domain.expression + +import java.lang.RuntimeException + +@JvmInline +value class Expression( + val value: String = "" +) { + + init { + require(value.isNotEmpty()) { throw RuntimeException() } + } + + fun splitExpression(): List { + return value.split("[,:]".toRegex()) + } + +} From 14be18e879ede3e852c8324473ce91e56d8f65a5 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Thu, 9 Nov 2023 23:38:48 +0900 Subject: [PATCH 03/92] =?UTF-8?q?feat=20:=20=EA=B3=84=EC=82=B0=EA=B8=B0=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20(=20Calculator=20)=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/domain/calculator/Calculator.kt | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/main/kotlin/camp/nextstep/edu/step/domain/calculator/Calculator.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/domain/calculator/Calculator.kt b/src/main/kotlin/camp/nextstep/edu/step/domain/calculator/Calculator.kt new file mode 100644 index 0000000000..5ccf9d0437 --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/domain/calculator/Calculator.kt @@ -0,0 +1,28 @@ +package camp.nextstep.edu.step.domain.calculator + +import camp.nextstep.edu.step.domain.amount.FinalResult + +/** + * @description : 계산식에서 나온 계산식을 토대로 계산을 진행하는 일급 컬렉션 + */ +data class Calculator( + val expressions: List +) { + + fun calculateExpression(): FinalResult { + var midResult = 0 + + for(expression in expressions) { + midResult = midResult.plus(expression.toInt()) + } + + return FinalResult(amount = midResult) + } + + companion object { + fun of(expressions: List): Calculator { + return Calculator(expressions) + } + } + +} From 0a66c23fed7f7c69a9679d47fa7aed0b60d04413 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Thu, 9 Nov 2023 23:39:22 +0900 Subject: [PATCH 04/92] =?UTF-8?q?feat=20:=20=EC=B5=9C=EC=A2=85=20=EB=8B=B5?= =?UTF-8?q?=20=EB=8F=84=EB=A9=94=EC=9D=B8=20(=20FinalResult=20)=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/nextstep/edu/step/domain/amount/FinalResult.kt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/main/kotlin/camp/nextstep/edu/step/domain/amount/FinalResult.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/domain/amount/FinalResult.kt b/src/main/kotlin/camp/nextstep/edu/step/domain/amount/FinalResult.kt new file mode 100644 index 0000000000..55ff774046 --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/domain/amount/FinalResult.kt @@ -0,0 +1,7 @@ +package camp.nextstep.edu.step.domain.amount + +@JvmInline +value class FinalResult( + val amount: Int +) { +} From cc8a3d9564d9049f4a5624c6edde82e2c930218f Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Thu, 9 Nov 2023 23:39:59 +0900 Subject: [PATCH 05/92] =?UTF-8?q?test=20:=20=EB=AC=B8=EC=9E=90=EC=97=B4=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20(=20Expression=20)=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step/domain/expression/ExpressionTest.kt | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/test/kotlin/camp/nextstep/edu/step/domain/expression/ExpressionTest.kt diff --git a/src/test/kotlin/camp/nextstep/edu/step/domain/expression/ExpressionTest.kt b/src/test/kotlin/camp/nextstep/edu/step/domain/expression/ExpressionTest.kt new file mode 100644 index 0000000000..f2f47fa7cf --- /dev/null +++ b/src/test/kotlin/camp/nextstep/edu/step/domain/expression/ExpressionTest.kt @@ -0,0 +1,38 @@ +package camp.nextstep.edu.step.domain.expression + +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.DisplayName + +@DisplayName("입력값은") +class ExpressionTest : BehaviorSpec({ + + Given("입력값이 주어지고") { + val emptyInputValue = "" + + When("0또는 Null이 주어지면") { + val emptyExpressionCreateException = shouldThrow { + Expression(value = emptyInputValue) + } + + Then("예외가 발생한다.") { + emptyExpressionCreateException shouldBe RuntimeException() + } + } + } + + Given("문자열이 주어졌을떄") { + val expressionRequest = "1,2:3" + + When("쉼표 또는 콜론으로 구분되어 있으면") { + val expression = Expression(value = expressionRequest) + val splitExpression = expression.splitExpression() + Then("쉼표 또는 콜론을 통해 문자열식을 분리한다.") { + splitExpression.size shouldBe 3 + splitExpression shouldBe listOf("1", "2", "3") + } + } + } + +}) From d87ee8b6de9324ba67222c8a1f13ad72f8755b1e Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Thu, 9 Nov 2023 23:40:19 +0900 Subject: [PATCH 06/92] =?UTF-8?q?test=20:=20=EA=B3=84=EC=82=B0=EA=B8=B0=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20(=20Calculator=20)=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=A7=84?= =?UTF-8?q?=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step/domain/calculator/CalculatorTest.kt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/test/kotlin/camp/nextstep/edu/step/domain/calculator/CalculatorTest.kt diff --git a/src/test/kotlin/camp/nextstep/edu/step/domain/calculator/CalculatorTest.kt b/src/test/kotlin/camp/nextstep/edu/step/domain/calculator/CalculatorTest.kt new file mode 100644 index 0000000000..3db5f133ac --- /dev/null +++ b/src/test/kotlin/camp/nextstep/edu/step/domain/calculator/CalculatorTest.kt @@ -0,0 +1,22 @@ +package camp.nextstep.edu.step.domain.calculator + +import camp.nextstep.edu.step.domain.amount.FinalResult +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe + +class CalculatorTest : BehaviorSpec({ + + Given("특수문자가 구분된 숫자들 리스트가 주어지고") { + val numbers = listOf("1", "2", "3") + + When("계산기에 숫자 리스트를 넣으면") { + val calculator = Calculator.of(expressions = numbers) + val result = calculator.calculateExpression() + + Then("숫자들의 합을 반환한다.") { + result shouldBe FinalResult(amount = 6) + } + } + } + +}) From e46cf58eef55e94453b0b36dbd3fe5725540e4f6 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Thu, 9 Nov 2023 23:40:28 +0900 Subject: [PATCH 07/92] =?UTF-8?q?docs=20:=20Readme=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cbae739405..c8c7035ebe 100644 --- a/README.md +++ b/README.md @@ -1 +1,11 @@ -# kotlin-lotto \ No newline at end of file +# kotlin-lotto + +# Step1 - 문자열 덧셈 계산기 +## 도메인 ( Domain ) +- 문자열 식 ( Expression ) +- 계산기 ( Calculator ) +- 결과 값 ( FinalResult ) + +## 고려해야하는 사항 +- 음수가 입력되어 있을 경우 예외를 처리해야한다 ( Runtime Exception ) +- 구분자는 , 외 : 도 사용할 수 있다. From 74ce73db1de377161a07d1027edf279ae7805ec3 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Sun, 12 Nov 2023 22:29:04 +0900 Subject: [PATCH 08/92] =?UTF-8?q?feat=20:=20=EA=B5=AC=EB=A7=A4=20=EA=B8=88?= =?UTF-8?q?=EC=95=A1=20=EB=8F=84=EB=A9=94=EC=9D=B8=20(=20BuyAmount=20)=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step2/domain/amount/BuyAmount.kt | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/domain/amount/BuyAmount.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/amount/BuyAmount.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/amount/BuyAmount.kt new file mode 100644 index 0000000000..e5e6948b51 --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/amount/BuyAmount.kt @@ -0,0 +1,23 @@ +package camp.nextstep.edu.step.step2.domain.amount + +import java.math.BigDecimal + +@JvmInline +value class BuyAmount( + private val amount: BigDecimal +) { + init { + require(amount > BigDecimal.ZERO) { "구매 금액은 0보다 커야 합니다." } + } + + fun getAmount(): BigDecimal { + return amount + } + + companion object { + fun of(amount: Long): BuyAmount { + return BuyAmount(BigDecimal.valueOf(amount)) + } + } + +} From fec11edb30df093b3d08039543e982b938c7e42f Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Sun, 12 Nov 2023 22:29:28 +0900 Subject: [PATCH 09/92] =?UTF-8?q?feat=20:=20=EB=A1=9C=EB=98=90=20=ED=8B=B0?= =?UTF-8?q?=EC=BC=93=20=EB=8F=84=EB=A9=94=EC=9D=B8=20(=20LottoTickets=20)?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step/step2/domain/store/LottoTickets.kt | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoTickets.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoTickets.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoTickets.kt new file mode 100644 index 0000000000..4f69ecccfc --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoTickets.kt @@ -0,0 +1,34 @@ +package camp.nextstep.edu.step.step2.domain.store + +import camp.nextstep.edu.step.step2.domain.lotto.Numbers + +@JvmInline +value class LottoTickets( + private val lottoTicketAmount: Int +) { + + init { + require(lottoTicketAmount > 0) { "로또 티켓은 1개 이상이어야 합니다." } + } + + fun getLottoTicketAmount(): Int { + return lottoTicketAmount + } + + /** + * @description : 로또 티켓 수량에 따른 로또 번호를 생성한다. + */ + fun createNumbersByLottoTicketAmount(): List { + return (1..lottoTicketAmount) + .map { Numbers(numbers = Numbers.createNumbers()) } + .distinct() + } + + + companion object { + fun of(lottoTicketAmount: Int): LottoTickets { + return LottoTickets(lottoTicketAmount) + } + } + +} From 51d49f72967cf8907bed7adc709af2268c075c6b Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Sun, 12 Nov 2023 22:29:39 +0900 Subject: [PATCH 10/92] =?UTF-8?q?feat=20:=20=EB=A1=9C=EB=98=90=20=EC=83=81?= =?UTF-8?q?=EC=A0=90=20(=20LottoStore=20)=20=EB=8F=84=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step2/domain/store/LottoStore.kt | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt new file mode 100644 index 0000000000..aa262df440 --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt @@ -0,0 +1,36 @@ +package camp.nextstep.edu.step.step2.domain.store + +import camp.nextstep.edu.step.step2.domain.amount.BuyAmount +import camp.nextstep.edu.step.step2.domain.lotto.Numbers +import camp.nextstep.edu.step.step2.domain.result.LottoMatch +import camp.nextstep.edu.step.step2.domain.result.LottoResult + +object LottoStore { + private const val LOTTO_TICKET_PRICE = 1000 + + /** + * @description : 구매금액에 따른 로또 티켓 수량을 구한다. + */ + fun buyLottoTickets(buyAmount: BuyAmount): LottoTickets { + val lottoTicketAmount = + buyAmount.getAmount().divide(LOTTO_TICKET_PRICE.toBigDecimal()).toInt() + return LottoTickets(lottoTicketAmount) + } + + /** + * @description : 로또의 당첨결과르 확인한다. ( 보통 로또의 경우 구매처에서 용지를 넣고 확인하는 방식을 활용했다. ) + */ + fun checkLottoTicketsWinningResult( + lottoNumbers: List, + lastWeekNumbers: Numbers + ): LottoResult { + val totalPrice = lottoNumbers.size * LOTTO_TICKET_PRICE + val matchResult = lottoNumbers + .map { numbers -> numbers.countMatch(lastWeekNumbers) } + .map { LottoMatch.of(it) } + .sorted() + + return LottoResult(totalPrice, matchResult) + } + +} From 753e16d0255dfddd4f65b9e8fc622b57b3c39ba0 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Sun, 12 Nov 2023 22:30:58 +0900 Subject: [PATCH 11/92] =?UTF-8?q?feat=20:=20=EB=A1=9C=EB=98=90=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20=EB=8F=84=EB=A9=94=EC=9D=B8=EA=B3=BC=20=EB=A7=A4?= =?UTF-8?q?=EC=B9=98=20=EA=B3=84=EC=82=B0=20Enum=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step/step2/domain/result/LottoMatch.kt | 19 ++++++++++++++ .../step/step2/domain/result/LottoResult.kt | 26 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoMatch.kt create mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResult.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoMatch.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoMatch.kt new file mode 100644 index 0000000000..99644e4d95 --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoMatch.kt @@ -0,0 +1,19 @@ +package camp.nextstep.edu.step.step2.domain.result + +enum class LottoMatch( + val matchCount: Int, + val prize: Int +) { + SIX_MATCH(6, 2_000_000_000), + FIVE_MATCH(5, 1_500_000), + FOUR_MATCH(4, 50_000), + THREE_MATCH(3, 5_000), + NONE(0, 0); + + + companion object { + fun of(matchCount: Int): LottoMatch { + return values().find { it.matchCount == matchCount } ?: NONE + } + } +} diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResult.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResult.kt new file mode 100644 index 0000000000..4149cb025c --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResult.kt @@ -0,0 +1,26 @@ +package camp.nextstep.edu.step.step2.domain.result + +data class LottoResult( + private val lottoTotalPrice: Int, + private val lottoResults: List +) { + + init { + require(lottoTotalPrice > 0) { "로또의 총 금액은 0보다 커야합니다." } + } + + fun calculateProfitRate(): Double { + return lottoResults.sumOf { it.prize }.toDouble() / lottoTotalPrice + } + + fun getResultCount(lottoMatch: LottoMatch): Int { + return lottoResults.count { it == lottoMatch } + } + + companion object { + fun of(lottoTotalPrice: Int, lottoResults: List): LottoResult { + return LottoResult(lottoTotalPrice, lottoResults) + } + } + +} From 40ad192ff89b5795fab35729fa5c4f04c3818ae1 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Sun, 12 Nov 2023 22:31:16 +0900 Subject: [PATCH 12/92] =?UTF-8?q?feat=20:=20=EB=A1=9C=EB=98=90=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EB=8F=84=EB=A9=94=EC=9D=B8=20(=20Number,=20Numbers?= =?UTF-8?q?=20)=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step2/domain/lotto/Number.kt | 22 +++++++++ .../edu/step/step2/domain/lotto/Numbers.kt | 49 +++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Number.kt create mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Numbers.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Number.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Number.kt new file mode 100644 index 0000000000..78878999e3 --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Number.kt @@ -0,0 +1,22 @@ +package camp.nextstep.edu.step.step2.domain.lotto + +@JvmInline +value class Number( + private val number: Int +) { + + init { + require(number in 1..45) { "로또 번호는 1~45 사이여야 합니다." } + } + + fun getNumber(): Int { + return number + } + + companion object { + fun of(number: Int): Number { + return Number(number) + } + } + +} diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Numbers.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Numbers.kt new file mode 100644 index 0000000000..e4cb79b5da --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Numbers.kt @@ -0,0 +1,49 @@ +package camp.nextstep.edu.step.step2.domain.lotto + +@JvmInline +value class Numbers( + private val numbers: List +) { + + init { + require(numbers.size == numbers.distinct().size) { "로또 번호는 중복될 수 없습니다." } + } + + fun getNumberElements(): List { + return numbers.map { it.getNumber() } + } + + fun countMatch(targetNumbers: Numbers): Int { + return numbers.count { targetNumbers.getNumberElements().contains(it.getNumber()) } + } + + companion object { + fun ofNumbers(numbers: List): Numbers { + return Numbers(numbers) + } + + fun ofInputValues(numbers: String): Numbers { + val numberList = numbers.split(",") + .map { it.trim() } + .map { Number.of(it.toInt()) } + return Numbers(numberList) + } + + /** + * @description : 로또 번호를 생성한다. + */ + fun createNumbers(): List { + val numbers = (START_NUMBER..END_NUMBER) + .shuffled() + .subList(0, NUMBER_SIZE) + .sorted() + + return numbers.map { Number.of(it) } + } + + private const val NUMBER_SIZE = 6 + private const val START_NUMBER = 1 + private const val END_NUMBER = 45 + } + +} From b50480cca54070e8f119eecc93045787070106b8 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Sun, 12 Nov 2023 22:31:27 +0900 Subject: [PATCH 13/92] =?UTF-8?q?feat=20:=20=EB=A1=9C=EB=98=90=20UI=20View?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nextstep/edu/step/step2/view/InputView.kt | 18 +++++++++++++ .../edu/step/step2/view/OutputView.kt | 27 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt create mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt new file mode 100644 index 0000000000..c85b1ccbd3 --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt @@ -0,0 +1,18 @@ +package camp.nextstep.edu.step.step2.view + +import camp.nextstep.edu.step.step2.domain.amount.BuyAmount +import camp.nextstep.edu.step.step2.domain.lotto.Numbers + +class InputView { + + fun getInputValueAndReturnBuyAmount(): BuyAmount { + println("구입금액을 입력해 주세요.") + return BuyAmount.of(readLine()!!.toLong()) + } + + fun inputLastWeekWinningNumbers(): Numbers { + println("지난 주 당첨 번호를 입력해 주세요.") + return Numbers.ofInputValues(numbers = readLine()!!) + } + +} diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt new file mode 100644 index 0000000000..5b5b54b5ce --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt @@ -0,0 +1,27 @@ +package camp.nextstep.edu.step.step2.view + +import camp.nextstep.edu.step.step2.domain.lotto.Numbers +import camp.nextstep.edu.step.step2.domain.result.LottoMatch +import camp.nextstep.edu.step.step2.domain.result.LottoResult +import camp.nextstep.edu.step.step2.domain.store.LottoTickets + +class OutputView { + + fun displayTicketsNumbers(lottoTickets: LottoTickets, ticketNumbers: List) { + println("${lottoTickets.getLottoTicketAmount()}개를 구매했습니다.") + + for (ticketNumber in ticketNumbers) { + println(ticketNumber.getNumberElements()) + } + } + + fun displayLottoResult(lottoResult: LottoResult) { + println("당첨 통계") + println("---------") + LottoMatch.values().reversed().forEach { + val count = lottoResult.getResultCount(it) + println("${it.matchCount}개 일치 (${it.prize}원) - ${count}개") + } + println("총 수익률은 ${lottoResult.calculateProfitRate()}입니다.") + } +} From 5dd6702d26e0b23dfb4e85cf13e051ba6b42f955 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Sun, 12 Nov 2023 22:31:39 +0900 Subject: [PATCH 14/92] =?UTF-8?q?feat=20:=20=EB=A1=9C=EB=98=90=20=EC=8B=A4?= =?UTF-8?q?=ED=96=89=EC=9D=84=20=EC=9C=84=ED=95=9C=20Main=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/nextstep/edu/step/step2/main.kt | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/main.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt new file mode 100644 index 0000000000..bafa40c02c --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt @@ -0,0 +1,29 @@ +package camp.nextstep.edu.step.step2 + +import camp.nextstep.edu.step.step2.domain.store.LottoStore +import camp.nextstep.edu.step.step2.view.InputView +import camp.nextstep.edu.step.step2.view.OutputView + +fun main() { + val inputView = InputView() + val outputView = OutputView() + + val buyAmount = inputView.getInputValueAndReturnBuyAmount() + val tickets = LottoStore.buyLottoTickets(buyAmount = buyAmount) + + val ticketsNumbers = tickets.createNumbersByLottoTicketAmount() + + outputView.displayTicketsNumbers( + lottoTickets = tickets, + ticketNumbers = ticketsNumbers + ) + + val lastWeekWinningNumbers = inputView.inputLastWeekWinningNumbers() + + val lottoResult = LottoStore.checkLottoTicketsWinningResult( + lottoNumbers = ticketsNumbers, + lastWeekNumbers = lastWeekWinningNumbers + ) + + outputView.displayLottoResult(lottoResult = lottoResult) +} From 4cf6c5d21c2cc2640e47d0c4c08a39dadea27052 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Sun, 12 Nov 2023 22:31:57 +0900 Subject: [PATCH 15/92] =?UTF-8?q?test=20:=20=EB=A1=9C=EB=98=90=20=EA=B5=AC?= =?UTF-8?q?=EB=A7=A4=20=EA=B8=88=EC=95=A1=20=EB=8F=84=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step/step2/domain/amount/BuyAmountTest.kt | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/test/kotlin/camp/nextstep/edu/step/step2/domain/amount/BuyAmountTest.kt diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/amount/BuyAmountTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/amount/BuyAmountTest.kt new file mode 100644 index 0000000000..7e9ac4860c --- /dev/null +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/amount/BuyAmountTest.kt @@ -0,0 +1,38 @@ +package camp.nextstep.edu.step.step2.domain.amount + +import camp.nextstep.edu.step.step2.domain.amount.BuyAmount +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.DisplayName +import java.math.BigDecimal + +@DisplayName("구매 금액은") +class BuyAmountTest : BehaviorSpec({ + + Given("구매 금액이 주어지고") { + val money = 14000L + + When("생성을 요청하면") { + val buyAmount = BuyAmount.of(amount = money) + + Then("주어진 구매 금액이 생성된다") { + buyAmount.getAmount() shouldBe BigDecimal.valueOf(14000L) + } + } + } + + Given("만약, 구매금액이 0원이 주어지고") { + val money = 0L + + When("생성을 요청하면") { + val buyAmount = shouldThrow { + BuyAmount.of(amount = money) + } + + Then("예외가 발생한다") { + buyAmount.message shouldBe "구매 금액은 0보다 커야 합니다." + } + } + } +}) From 9ea8a0eb390ec4bc77ce004a6a2cf8f2bd885e6b Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Sun, 12 Nov 2023 22:32:09 +0900 Subject: [PATCH 16/92] =?UTF-8?q?test=20:=20=EB=A1=9C=EB=98=90=20=ED=8B=B0?= =?UTF-8?q?=EC=BC=93=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step2/domain/lotto/LottoTicketsTest.kt | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTicketsTest.kt diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTicketsTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTicketsTest.kt new file mode 100644 index 0000000000..b712f4f03e --- /dev/null +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTicketsTest.kt @@ -0,0 +1,65 @@ +package camp.nextstep.edu.step.step2.domain.lotto + +import camp.nextstep.edu.step.step2.domain.store.LottoTickets +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.DisplayName + +@DisplayName("로또 티켓은") +class LottoTicketsTest : BehaviorSpec({ + + Given("티켓 수량이 주어지면") { + val ticketAmount = 1 + + When("생성 시") { + val lottoTickets = LottoTickets.of(ticketAmount) + + Then("주어진 수량만큼의 로또 티켓이 생성된다") { + assertEquals(lottoTickets.getLottoTicketAmount(), 1) + } + } + } + + Given("로또 티켓이 생성되고") { + val lottoTickets = LottoTickets.of(lottoTicketAmount = 5) + + When("로또 번호 생성시") { + val lottoNumbers = lottoTickets.createNumbersByLottoTicketAmount() + + Then("주어진 티켓 수만큼 로또 번호가 생성된다") { + println(lottoNumbers) + assertEquals(lottoNumbers.size, 5) + } + } + } + + Given("만약 구매금액이 0원일 경우") { + val buyAmount = 0 + + When("생성시") { + val lottoTickets = shouldThrow { + LottoTickets.of(lottoTicketAmount = buyAmount) + } + + Then("예외가 발생한다") { + lottoTickets.message shouldBe "로또 티켓은 1개 이상이어야 합니다." + } + } + } + + Given("로또 티켓이 주어지고") { + val ticketAmount = 1 + val lottoTickets = LottoTickets.of(ticketAmount) + + When("숫자 생성을 요청하면") { + val lottoNumbers = lottoTickets.createNumbersByLottoTicketAmount() + + Then("구매 수량만큼 로또번호가 생성된다.") { + lottoNumbers.size shouldBe 1 + } + } + } + +}) From 65184a90d62456dc6337ed58c818e549cd3540aa Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Sun, 12 Nov 2023 22:32:24 +0900 Subject: [PATCH 17/92] =?UTF-8?q?test=20:=20=EB=A1=9C=EB=98=90=20=ED=8B=B0?= =?UTF-8?q?=EC=BC=93=20=EB=84=98=EB=B2=84=20=EB=8F=84=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?(=20Number,=20Numbers=20)=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step2/domain/lotto/NumberTest.kt | 37 ++++++++++ .../step/step2/domain/lotto/NumbersTest.kt | 72 +++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumberTest.kt create mode 100644 src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumbersTest.kt diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumberTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumberTest.kt new file mode 100644 index 0000000000..20643a34b9 --- /dev/null +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumberTest.kt @@ -0,0 +1,37 @@ +package camp.nextstep.edu.step.step2.domain.lotto + +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.DisplayName + +@DisplayName("로또 번호는") +class NumberTest : BehaviorSpec({ + + Given("1~45 사이의 숫자가 주어지고") { + val number = 1 + + When("생성을 요청하면") { + val lottoNumber = Number.of(number) + + Then("주어진 숫자가 생성된다") { + lottoNumber shouldBe Number.of(1) + } + } + } + + Given("만약 1~45 사이가 아닐경우") { + val number = 46 + + When("생성을 요청하면") { + val lottoNumber = shouldThrow { + Number.of(number) + } + + Then("예외가 발생한다") { + lottoNumber.message shouldBe "로또 번호는 1~45 사이여야 합니다." + } + } + } + +}) diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumbersTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumbersTest.kt new file mode 100644 index 0000000000..ce049067b9 --- /dev/null +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumbersTest.kt @@ -0,0 +1,72 @@ +package camp.nextstep.edu.step.step2.domain.lotto + +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.DisplayName + +@DisplayName("로또 번호들은") +class NumbersTest : BehaviorSpec({ + + Given("로또 번호들이 주어지고") { + val requestNumbers = listOf( + Number(number = 1), + Number(number = 2), + Number(number = 3), + Number(number = 4), + Number(number = 5), + Number(number = 6) + ) + + When("생성을 요청하면") { + val numbers = Numbers.ofNumbers(numbers = requestNumbers) + + Then("주어진 로또 번호들이 생성된다") { + numbers shouldBe Numbers.ofNumbers( + numbers = listOf( + Number(number = 1), + Number(number = 2), + Number(number = 3), + Number(number = 4), + Number(number = 5), + Number(number = 6) + ) + ) + } + } + } + + + Given("만약 중복인 숫자가 포함되어 있을 경우") { + val requestNumbers = listOf( + Number(number = 1), + Number(number = 2), + Number(number = 3), + Number(number = 4), + Number(number = 5), + Number(number = 5) + ) + + When("생성을 요청하면") { + val numbers = shouldThrow { + Numbers.ofNumbers(numbers = requestNumbers) + } + + Then("예외가 발생한다") { + numbers.message shouldBe "로또 번호는 중복될 수 없습니다." + } + } + } + + Given("로또의 번호들은") { + + When("새로운 번호 생성 요청이 들어오면") { + val numbers = Numbers.createNumbers() + + Then("6개의 번호가 생성된다") { + numbers.size shouldBe 6 + } + } + } + +}) From 1d00badcced9e0d6717788b17db2718cc4808317 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Sun, 12 Nov 2023 22:32:35 +0900 Subject: [PATCH 18/92] =?UTF-8?q?test=20:=20=EB=A1=9C=EB=98=90=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step2/domain/result/LottoResultTest.kt | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt new file mode 100644 index 0000000000..51a166efde --- /dev/null +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt @@ -0,0 +1,42 @@ +package camp.nextstep.edu.step.step2.domain.result + +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.DisplayName + +@DisplayName("로또 결과는") +class LottoResultTest : BehaviorSpec({ + + Given("로또의 총 금액과, 매치 결과가 주어지면") { + val totalPrice = 1000 + val matchResult = listOf(LottoMatch.of(matchCount = 6)) + + When("로또 결과를 생성하면") { + val lottoResult = + LottoResult.of(lottoTotalPrice = totalPrice, lottoResults = matchResult) + + Then("로또 결과가 생성된다") { + lottoResult shouldBe LottoResult.of( + lottoTotalPrice = 1000, + lottoResults = listOf(LottoMatch.of(matchCount = 6)) + ) + } + } + } + + Given("로또 결과 객체가 주어지고") { + val totalPrice = 1000 + val matchResult = listOf(LottoMatch.of(matchCount = 6)) + + val lottoResult = + LottoResult.of(lottoTotalPrice = totalPrice, lottoResults = matchResult) + + When("로또 통계율 계산을 시도하면") { + val result = lottoResult.calculateProfitRate() + + Then("로또 통계율이 계산된다") { + result shouldBe 2000000.0 + } + } + } +}) From 8fcae3876b904b80db765f1e5193c8d619a32cc1 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Sun, 12 Nov 2023 22:32:42 +0900 Subject: [PATCH 19/92] =?UTF-8?q?test=20:=20=EB=A1=9C=EB=98=90=20=EC=83=81?= =?UTF-8?q?=EC=A0=90=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step/step2/domain/store/LottoStoreTest.kt | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt new file mode 100644 index 0000000000..f17cc7a147 --- /dev/null +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt @@ -0,0 +1,69 @@ +package camp.nextstep.edu.step.step2.domain.store + +import camp.nextstep.edu.step.step2.domain.amount.BuyAmount +import camp.nextstep.edu.step.step2.domain.lotto.Number +import camp.nextstep.edu.step.step2.domain.lotto.Numbers +import camp.nextstep.edu.step.step2.domain.result.LottoMatch +import camp.nextstep.edu.step.step2.domain.result.LottoResult +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.DisplayName +import java.math.BigDecimal + +@DisplayName("로또 상점은") +class LottoStoreTest : BehaviorSpec({ + + Given("구입 금액이 주어지고") { + val buyAmount = BuyAmount(amount = BigDecimal.valueOf(10000L)) + + When("로또를 구매하면") { + val lottoTickets = LottoStore.buyLottoTickets(buyAmount) + + Then("구매한 금액만큼의 로또 티켓 수를 반환한다.") { + lottoTickets.getLottoTicketAmount() shouldBe 10 + } + } + } + + Given("로또번호와 이전 당첨번호를 입력하게되고") { + val lottoNumbers = listOf( + Numbers.ofNumbers( + listOf( + Number.of(1), + Number.of(2), + Number.of(3), + Number.of(4), + Number.of(5), + Number.of(6) + ) + ) + ) + + val lastWeekWinningLottoNumbers = Numbers.ofNumbers( + listOf( + Number.of(1), + Number.of(2), + Number.of(3), + Number.of(4), + Number.of(5), + Number.of(6) + ) + ) + + When("로또 번호를 검증하면") { + val lottoResult = + LottoStore.checkLottoTicketsWinningResult(lottoNumbers, lastWeekWinningLottoNumbers) + + Then("로또 결과를 반환한다.") { + lottoResult shouldBe LottoResult.of( + lottoTotalPrice = 1000, + lottoResults = listOf( + LottoMatch.of( + matchCount = 6 + ) + ) + ) + } + } + } +}) From b684a56c7bc622306d1ebd9db5700ceada215765 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Sun, 12 Nov 2023 22:32:59 +0900 Subject: [PATCH 20/92] =?UTF-8?q?docs=20:=20=EB=A1=9C=EB=98=90=20=EA=B3=BC?= =?UTF-8?q?=EC=A0=9C=20README=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/README.md b/README.md index c8c7035ebe..a5be827d03 100644 --- a/README.md +++ b/README.md @@ -9,3 +9,30 @@ ## 고려해야하는 사항 - 음수가 입력되어 있을 경우 예외를 처리해야한다 ( Runtime Exception ) - 구분자는 , 외 : 도 사용할 수 있다. + + +# Step2 - 로또 ( Lotto ) +## 도메인 ( Domain ) +- 구매금액 ( BuyAmount ) +- 로또 번호 ( LottoNumber ) +- 로또 번호들 ( LottoNumbers ) +- 로또 상점 ( LottoStore ) +- 구매한 로또 티켓들 ( LottoTickets ) +- 로또 결과 ( LottoResult ) + +## 고려해야하는 사항 +- 구매금액 + - 구매 금액은 0원보다 많아야 한다. + - 로또의 한장 가격은 1000원이다. +- 로또 상점 + - 구매 금액에 따른 로또번호 발급이 이뤄진다. + - 이전 당첨 번호 입력을 통해 당첨 내역 확인이 가능하다. +- 로또 번호 + - 로또 번호는 1 ~ 45 사이의 숫자이다. + - 로또 번호는 중복될 수 없다. +- 로또 티켓 + - 로또 티켓은 구매한 수량만큼 번호가 생성된다. +- 로또 결과 + - 당첨 내용에 따른 통계 계산이 가능하다. + - 이전 당첨번호를 통해 당첨 여부 확인이 가능하다. + - 로또의 총 금액은 0보다 커야한다. From 33bb4c70dc621e762bf05c4df78665e1502ff65b Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Sun, 12 Nov 2023 22:33:17 +0900 Subject: [PATCH 21/92] =?UTF-8?q?chore=20:=20=EC=9B=90=ED=99=9C=ED=95=9C?= =?UTF-8?q?=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EA=B4=80=EB=A6=AC=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20=EC=9D=B4=EC=A0=84=20=ED=95=AD=EB=AA=A9=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/{ => step1}/domain/amount/FinalResult.kt | 2 +- .../edu/step/{ => step1}/domain/calculator/Calculator.kt | 4 ++-- .../edu/step/{ => step1}/domain/expression/Expression.kt | 2 +- .../edu/step/{ => step1}/domain/calculator/CalculatorTest.kt | 4 ++-- .../edu/step/{ => step1}/domain/expression/ExpressionTest.kt | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) rename src/main/kotlin/camp/nextstep/edu/step/{ => step1}/domain/amount/FinalResult.kt (55%) rename src/main/kotlin/camp/nextstep/edu/step/{ => step1}/domain/calculator/Calculator.kt (82%) rename src/main/kotlin/camp/nextstep/edu/step/{ => step1}/domain/expression/Expression.kt (83%) rename src/test/kotlin/camp/nextstep/edu/step/{ => step1}/domain/calculator/CalculatorTest.kt (83%) rename src/test/kotlin/camp/nextstep/edu/step/{ => step1}/domain/expression/ExpressionTest.kt (95%) diff --git a/src/main/kotlin/camp/nextstep/edu/step/domain/amount/FinalResult.kt b/src/main/kotlin/camp/nextstep/edu/step/step1/domain/amount/FinalResult.kt similarity index 55% rename from src/main/kotlin/camp/nextstep/edu/step/domain/amount/FinalResult.kt rename to src/main/kotlin/camp/nextstep/edu/step/step1/domain/amount/FinalResult.kt index 55ff774046..b0548e9756 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/domain/amount/FinalResult.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step1/domain/amount/FinalResult.kt @@ -1,4 +1,4 @@ -package camp.nextstep.edu.step.domain.amount +package camp.nextstep.edu.step.step1.domain.amount @JvmInline value class FinalResult( diff --git a/src/main/kotlin/camp/nextstep/edu/step/domain/calculator/Calculator.kt b/src/main/kotlin/camp/nextstep/edu/step/step1/domain/calculator/Calculator.kt similarity index 82% rename from src/main/kotlin/camp/nextstep/edu/step/domain/calculator/Calculator.kt rename to src/main/kotlin/camp/nextstep/edu/step/step1/domain/calculator/Calculator.kt index 5ccf9d0437..ee70455b1a 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/domain/calculator/Calculator.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step1/domain/calculator/Calculator.kt @@ -1,6 +1,6 @@ -package camp.nextstep.edu.step.domain.calculator +package camp.nextstep.edu.step.step1.domain.calculator -import camp.nextstep.edu.step.domain.amount.FinalResult +import camp.nextstep.edu.step.step1.domain.amount.FinalResult /** * @description : 계산식에서 나온 계산식을 토대로 계산을 진행하는 일급 컬렉션 diff --git a/src/main/kotlin/camp/nextstep/edu/step/domain/expression/Expression.kt b/src/main/kotlin/camp/nextstep/edu/step/step1/domain/expression/Expression.kt similarity index 83% rename from src/main/kotlin/camp/nextstep/edu/step/domain/expression/Expression.kt rename to src/main/kotlin/camp/nextstep/edu/step/step1/domain/expression/Expression.kt index 55aa9bc0b8..d4a9265ebe 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/domain/expression/Expression.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step1/domain/expression/Expression.kt @@ -1,4 +1,4 @@ -package camp.nextstep.edu.step.domain.expression +package camp.nextstep.edu.step.step1.domain.expression import java.lang.RuntimeException diff --git a/src/test/kotlin/camp/nextstep/edu/step/domain/calculator/CalculatorTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step1/domain/calculator/CalculatorTest.kt similarity index 83% rename from src/test/kotlin/camp/nextstep/edu/step/domain/calculator/CalculatorTest.kt rename to src/test/kotlin/camp/nextstep/edu/step/step1/domain/calculator/CalculatorTest.kt index 3db5f133ac..9515090206 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/domain/calculator/CalculatorTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step1/domain/calculator/CalculatorTest.kt @@ -1,6 +1,6 @@ -package camp.nextstep.edu.step.domain.calculator +package camp.nextstep.edu.step.step1.domain.calculator -import camp.nextstep.edu.step.domain.amount.FinalResult +import camp.nextstep.edu.step.step1.domain.amount.FinalResult import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe diff --git a/src/test/kotlin/camp/nextstep/edu/step/domain/expression/ExpressionTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step1/domain/expression/ExpressionTest.kt similarity index 95% rename from src/test/kotlin/camp/nextstep/edu/step/domain/expression/ExpressionTest.kt rename to src/test/kotlin/camp/nextstep/edu/step/step1/domain/expression/ExpressionTest.kt index f2f47fa7cf..a4c82f5ae7 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/domain/expression/ExpressionTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step1/domain/expression/ExpressionTest.kt @@ -1,4 +1,4 @@ -package camp.nextstep.edu.step.domain.expression +package camp.nextstep.edu.step.step1.domain.expression import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.BehaviorSpec From a93a55a4d04907089fe0fc20c4337d3f5600242d Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Tue, 14 Nov 2023 13:58:03 +0900 Subject: [PATCH 22/92] =?UTF-8?q?chore=20:=20step1=20=EC=A4=91=EB=B3=B5=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=EB=93=A4=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/domain/amount/FinalResult.kt | 7 ---- .../edu/step/domain/calculator/Calculator.kt | 28 -------------- .../edu/step/domain/expression/Expression.kt | 18 --------- .../step/domain/calculator/CalculatorTest.kt | 22 ----------- .../step/domain/expression/ExpressionTest.kt | 38 ------------------- 5 files changed, 113 deletions(-) delete mode 100644 src/main/kotlin/camp/nextstep/edu/step/domain/amount/FinalResult.kt delete mode 100644 src/main/kotlin/camp/nextstep/edu/step/domain/calculator/Calculator.kt delete mode 100644 src/main/kotlin/camp/nextstep/edu/step/domain/expression/Expression.kt delete mode 100644 src/test/kotlin/camp/nextstep/edu/step/domain/calculator/CalculatorTest.kt delete mode 100644 src/test/kotlin/camp/nextstep/edu/step/domain/expression/ExpressionTest.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/domain/amount/FinalResult.kt b/src/main/kotlin/camp/nextstep/edu/step/domain/amount/FinalResult.kt deleted file mode 100644 index 55ff774046..0000000000 --- a/src/main/kotlin/camp/nextstep/edu/step/domain/amount/FinalResult.kt +++ /dev/null @@ -1,7 +0,0 @@ -package camp.nextstep.edu.step.domain.amount - -@JvmInline -value class FinalResult( - val amount: Int -) { -} diff --git a/src/main/kotlin/camp/nextstep/edu/step/domain/calculator/Calculator.kt b/src/main/kotlin/camp/nextstep/edu/step/domain/calculator/Calculator.kt deleted file mode 100644 index 5ccf9d0437..0000000000 --- a/src/main/kotlin/camp/nextstep/edu/step/domain/calculator/Calculator.kt +++ /dev/null @@ -1,28 +0,0 @@ -package camp.nextstep.edu.step.domain.calculator - -import camp.nextstep.edu.step.domain.amount.FinalResult - -/** - * @description : 계산식에서 나온 계산식을 토대로 계산을 진행하는 일급 컬렉션 - */ -data class Calculator( - val expressions: List -) { - - fun calculateExpression(): FinalResult { - var midResult = 0 - - for(expression in expressions) { - midResult = midResult.plus(expression.toInt()) - } - - return FinalResult(amount = midResult) - } - - companion object { - fun of(expressions: List): Calculator { - return Calculator(expressions) - } - } - -} diff --git a/src/main/kotlin/camp/nextstep/edu/step/domain/expression/Expression.kt b/src/main/kotlin/camp/nextstep/edu/step/domain/expression/Expression.kt deleted file mode 100644 index 55aa9bc0b8..0000000000 --- a/src/main/kotlin/camp/nextstep/edu/step/domain/expression/Expression.kt +++ /dev/null @@ -1,18 +0,0 @@ -package camp.nextstep.edu.step.domain.expression - -import java.lang.RuntimeException - -@JvmInline -value class Expression( - val value: String = "" -) { - - init { - require(value.isNotEmpty()) { throw RuntimeException() } - } - - fun splitExpression(): List { - return value.split("[,:]".toRegex()) - } - -} diff --git a/src/test/kotlin/camp/nextstep/edu/step/domain/calculator/CalculatorTest.kt b/src/test/kotlin/camp/nextstep/edu/step/domain/calculator/CalculatorTest.kt deleted file mode 100644 index 3db5f133ac..0000000000 --- a/src/test/kotlin/camp/nextstep/edu/step/domain/calculator/CalculatorTest.kt +++ /dev/null @@ -1,22 +0,0 @@ -package camp.nextstep.edu.step.domain.calculator - -import camp.nextstep.edu.step.domain.amount.FinalResult -import io.kotest.core.spec.style.BehaviorSpec -import io.kotest.matchers.shouldBe - -class CalculatorTest : BehaviorSpec({ - - Given("특수문자가 구분된 숫자들 리스트가 주어지고") { - val numbers = listOf("1", "2", "3") - - When("계산기에 숫자 리스트를 넣으면") { - val calculator = Calculator.of(expressions = numbers) - val result = calculator.calculateExpression() - - Then("숫자들의 합을 반환한다.") { - result shouldBe FinalResult(amount = 6) - } - } - } - -}) diff --git a/src/test/kotlin/camp/nextstep/edu/step/domain/expression/ExpressionTest.kt b/src/test/kotlin/camp/nextstep/edu/step/domain/expression/ExpressionTest.kt deleted file mode 100644 index f2f47fa7cf..0000000000 --- a/src/test/kotlin/camp/nextstep/edu/step/domain/expression/ExpressionTest.kt +++ /dev/null @@ -1,38 +0,0 @@ -package camp.nextstep.edu.step.domain.expression - -import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.BehaviorSpec -import io.kotest.matchers.shouldBe -import org.junit.jupiter.api.DisplayName - -@DisplayName("입력값은") -class ExpressionTest : BehaviorSpec({ - - Given("입력값이 주어지고") { - val emptyInputValue = "" - - When("0또는 Null이 주어지면") { - val emptyExpressionCreateException = shouldThrow { - Expression(value = emptyInputValue) - } - - Then("예외가 발생한다.") { - emptyExpressionCreateException shouldBe RuntimeException() - } - } - } - - Given("문자열이 주어졌을떄") { - val expressionRequest = "1,2:3" - - When("쉼표 또는 콜론으로 구분되어 있으면") { - val expression = Expression(value = expressionRequest) - val splitExpression = expression.splitExpression() - Then("쉼표 또는 콜론을 통해 문자열식을 분리한다.") { - splitExpression.size shouldBe 3 - splitExpression shouldBe listOf("1", "2", "3") - } - } - } - -}) From 5150c5a962a6e4f43b37bf6461d1d0e6476d3142 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Tue, 14 Nov 2023 16:42:33 +0900 Subject: [PATCH 23/92] =?UTF-8?q?refactor=20:=20=EA=B3=84=EC=82=B0?= =?UTF-8?q?=EA=B8=B0=20=EB=8F=84=EB=A9=94=EC=9D=B8=20(=20Calculator=20)=20?= =?UTF-8?q?=EB=82=B4,=20=EB=AC=B8=EC=9E=90=EC=97=B4=20=EA=B3=84=EC=82=B0?= =?UTF-8?q?=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step1/domain/calculator/Calculator.kt | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step1/domain/calculator/Calculator.kt b/src/main/kotlin/camp/nextstep/edu/step/step1/domain/calculator/Calculator.kt index ee70455b1a..1b8d1f2e56 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step1/domain/calculator/Calculator.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step1/domain/calculator/Calculator.kt @@ -10,19 +10,13 @@ data class Calculator( ) { fun calculateExpression(): FinalResult { - var midResult = 0 - for(expression in expressions) { - midResult = midResult.plus(expression.toInt()) + val result = expressions.reduce { midResult, expression -> + val result = midResult.toInt() + expression.toInt() + result.toString() } - return FinalResult(amount = midResult) - } - - companion object { - fun of(expressions: List): Calculator { - return Calculator(expressions) - } + return FinalResult(amount = result.toInt()) } } From 2e4789b81cb9f48ded86659c7ded0f131a06e62c Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Tue, 14 Nov 2023 16:43:17 +0900 Subject: [PATCH 24/92] =?UTF-8?q?refactor=20:=20=EB=AC=B8=EC=9E=90?= =?UTF-8?q?=EC=97=B4=20=EC=8B=9D=20=EB=8F=84=EB=A9=94=EC=9D=B8=20(=20Expre?= =?UTF-8?q?ssion=20)=20=EB=82=B4,=20=EC=9D=8C=EC=88=98=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20private=20method=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step1/domain/expression/Expression.kt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step1/domain/expression/Expression.kt b/src/main/kotlin/camp/nextstep/edu/step/step1/domain/expression/Expression.kt index d4a9265ebe..e602f62009 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step1/domain/expression/Expression.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step1/domain/expression/Expression.kt @@ -1,7 +1,5 @@ package camp.nextstep.edu.step.step1.domain.expression -import java.lang.RuntimeException - @JvmInline value class Expression( val value: String = "" @@ -9,10 +7,17 @@ value class Expression( init { require(value.isNotEmpty()) { throw RuntimeException() } + validateNegativeExpression() } fun splitExpression(): List { return value.split("[,:]".toRegex()) } + private fun validateNegativeExpression() { + if (value.contains("-")) { + throw RuntimeException() + } + } + } From 19e267b81daeeec46410ff5125e6fa259ad49faf Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Tue, 14 Nov 2023 16:43:57 +0900 Subject: [PATCH 25/92] =?UTF-8?q?refactor=20:=20of=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=EB=A5=BC=20=ED=86=B5=ED=95=9C=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EB=82=B4,=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step1/domain/calculator/CalculatorTest.kt | 2 +- .../nextstep/edu/step/step2/domain/amount/BuyAmountTest.kt | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/test/kotlin/camp/nextstep/edu/step/step1/domain/calculator/CalculatorTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step1/domain/calculator/CalculatorTest.kt index 9515090206..3380dbf67f 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step1/domain/calculator/CalculatorTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step1/domain/calculator/CalculatorTest.kt @@ -10,7 +10,7 @@ class CalculatorTest : BehaviorSpec({ val numbers = listOf("1", "2", "3") When("계산기에 숫자 리스트를 넣으면") { - val calculator = Calculator.of(expressions = numbers) + val calculator = Calculator(expressions = numbers) val result = calculator.calculateExpression() Then("숫자들의 합을 반환한다.") { diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/amount/BuyAmountTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/amount/BuyAmountTest.kt index 7e9ac4860c..6cfda02405 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/amount/BuyAmountTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/amount/BuyAmountTest.kt @@ -1,6 +1,5 @@ package camp.nextstep.edu.step.step2.domain.amount -import camp.nextstep.edu.step.step2.domain.amount.BuyAmount import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe @@ -14,10 +13,10 @@ class BuyAmountTest : BehaviorSpec({ val money = 14000L When("생성을 요청하면") { - val buyAmount = BuyAmount.of(amount = money) + val buyAmount = BuyAmount(amount = money) Then("주어진 구매 금액이 생성된다") { - buyAmount.getAmount() shouldBe BigDecimal.valueOf(14000L) + buyAmount.amount shouldBe BigDecimal.valueOf(14000L) } } } @@ -27,7 +26,7 @@ class BuyAmountTest : BehaviorSpec({ When("생성을 요청하면") { val buyAmount = shouldThrow { - BuyAmount.of(amount = money) + BuyAmount(amount = money) } Then("예외가 발생한다") { From 240084d6bcd19a8f4fde2526c26005e7f254e39e Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Tue, 14 Nov 2023 17:32:36 +0900 Subject: [PATCH 26/92] =?UTF-8?q?refactor=20:=20Numbers=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=EC=9D=84=20Lotto=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20?= =?UTF-8?q?=EB=82=B4=EB=B6=80=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81=20?= =?UTF-8?q?=EC=A7=84=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step2/domain/lotto/Lotto.kt | 40 +++++++++++++++ .../edu/step/step2/domain/lotto/Numbers.kt | 49 ------------------- 2 files changed, 40 insertions(+), 49 deletions(-) create mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt delete mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Numbers.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt new file mode 100644 index 0000000000..4d7b878c4c --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt @@ -0,0 +1,40 @@ +package camp.nextstep.edu.step.step2.domain.lotto + +import camp.nextstep.edu.step.step2.generator.NumberGenerator +import camp.nextstep.edu.step.step2.generator.NumberGenerator.LOTTO_RANDOM + +@JvmInline +value class Lotto( + val numbers: List +) { + + fun getNumberElements(): List { + return numbers.map { it.number } + } + + fun countMatch(targetLotto: Lotto): Int { + return numbers.count { targetLotto.getNumberElements().contains(it.number) } + } + + companion object { + + fun ofInputValues(numbers: String): Lotto { + val numberList = numbers.split(",") + .map { it.trim() } + .map { Number(number = it.toInt()) } + return Lotto(numbers = numberList) + } + + /** + * @description : 로또 번호를 자동 생성한다. + */ + fun generateAutoNumbers(): Lotto { + val numbers = NumberGenerator.generate(LOTTO_RANDOM) + + val lottoNums = numbers.map { Number(number = it) } + + return Lotto(numbers = lottoNums) + } + } + +} diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Numbers.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Numbers.kt deleted file mode 100644 index e4cb79b5da..0000000000 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Numbers.kt +++ /dev/null @@ -1,49 +0,0 @@ -package camp.nextstep.edu.step.step2.domain.lotto - -@JvmInline -value class Numbers( - private val numbers: List -) { - - init { - require(numbers.size == numbers.distinct().size) { "로또 번호는 중복될 수 없습니다." } - } - - fun getNumberElements(): List { - return numbers.map { it.getNumber() } - } - - fun countMatch(targetNumbers: Numbers): Int { - return numbers.count { targetNumbers.getNumberElements().contains(it.getNumber()) } - } - - companion object { - fun ofNumbers(numbers: List): Numbers { - return Numbers(numbers) - } - - fun ofInputValues(numbers: String): Numbers { - val numberList = numbers.split(",") - .map { it.trim() } - .map { Number.of(it.toInt()) } - return Numbers(numberList) - } - - /** - * @description : 로또 번호를 생성한다. - */ - fun createNumbers(): List { - val numbers = (START_NUMBER..END_NUMBER) - .shuffled() - .subList(0, NUMBER_SIZE) - .sorted() - - return numbers.map { Number.of(it) } - } - - private const val NUMBER_SIZE = 6 - private const val START_NUMBER = 1 - private const val END_NUMBER = 45 - } - -} From 2172915a4d0ae199e2d39baf1f43994bc8417c7c Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Tue, 14 Nov 2023 17:33:27 +0900 Subject: [PATCH 27/92] =?UTF-8?q?refactor=20:=20=EA=B5=AC=EB=A7=A4?= =?UTF-8?q?=EA=B8=88=EC=95=A1=20=EB=8F=84=EB=A9=94=EC=9D=B8=20(=20BuyAmoun?= =?UTF-8?q?t=20)=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81=20=EC=A7=84?= =?UTF-8?q?=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step2/domain/amount/BuyAmount.kt | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/amount/BuyAmount.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/amount/BuyAmount.kt index e5e6948b51..dfa5b555ae 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/amount/BuyAmount.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/amount/BuyAmount.kt @@ -4,20 +4,16 @@ import java.math.BigDecimal @JvmInline value class BuyAmount( - private val amount: BigDecimal + val amount: BigDecimal ) { init { require(amount > BigDecimal.ZERO) { "구매 금액은 0보다 커야 합니다." } } - fun getAmount(): BigDecimal { - return amount - } + constructor(amount: Long) : this(BigDecimal.valueOf(amount)) - companion object { - fun of(amount: Long): BuyAmount { - return BuyAmount(BigDecimal.valueOf(amount)) - } + fun divideByLotteryPrice(ticketPrice: Long): Int { + return amount.divide(BigDecimal.valueOf(ticketPrice)).toInt() } } From c297adf2a558124025fbb1704b00dfeaf1fa915d Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Tue, 14 Nov 2023 17:34:07 +0900 Subject: [PATCH 28/92] =?UTF-8?q?refactor=20:=20=EC=88=AB=EC=9E=90=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20(=20Number=20)=20=EB=82=B4,=20pri?= =?UTF-8?q?vate=20=EC=A0=9C=EA=B1=B0=20=EB=B0=8F=20of=20,=20get=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nextstep/edu/step/step2/domain/lotto/Number.kt | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Number.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Number.kt index 78878999e3..858c08f577 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Number.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Number.kt @@ -2,21 +2,11 @@ package camp.nextstep.edu.step.step2.domain.lotto @JvmInline value class Number( - private val number: Int + val number: Int ) { init { require(number in 1..45) { "로또 번호는 1~45 사이여야 합니다." } } - fun getNumber(): Int { - return number - } - - companion object { - fun of(number: Int): Number { - return Number(number) - } - } - } From 5af7f10ff8764bacc86c5a072010d0d5c0f1c31b Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Tue, 14 Nov 2023 17:34:23 +0900 Subject: [PATCH 29/92] =?UTF-8?q?feat=20:=20=EB=A1=9C=EB=98=90=20=EB=8B=B9?= =?UTF-8?q?=EC=B2=A8=ED=99=95=EC=9D=B8=20=EB=8F=84=EB=A9=94=EC=9D=B8=20(?= =?UTF-8?q?=20WinningLotto=20)=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step/step2/domain/lotto/WinningLotto.kt | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt new file mode 100644 index 0000000000..6a4d5a5b65 --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt @@ -0,0 +1,26 @@ +package camp.nextstep.edu.step.step2.domain.lotto + +import camp.nextstep.edu.step.step2.domain.result.LottoMatch + +data class WinningLotto( + val userLottoTickets: List, + val winningLotto: Lotto, +) { + + init { + require(userLottoTickets.isNotEmpty()) { "구매한 로또가 없습니다." } + require(winningLotto.numbers.isNotEmpty()) { "당첨번호가 입력되지 않았습니다." } + } + + fun getTotalPriceByLottoAmountAndTicketPrice(ticketPrice: Long): Int { + return userLottoTickets.size * ticketPrice.toInt() + } + + fun getLottoMatchResult(): List { + return userLottoTickets + .map { numbers -> numbers.countMatch(winningLotto) } + .map { LottoMatch.of(it) } + .sorted() + } + +} From 8d1743e12d231d76685725f83c2279872e0848b4 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Tue, 14 Nov 2023 17:35:44 +0900 Subject: [PATCH 30/92] =?UTF-8?q?refactor=20:=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EC=B5=9C=EC=A2=85=20=EA=B2=B0=EA=B3=BC=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20(=20LottoResult=20)=20private=20=EC=A0=9C=EA=B1=B0?= =?UTF-8?q?=20=EB=B0=8F=20of=20=ED=95=A8=EC=88=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step2/domain/result/LottoResult.kt | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResult.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResult.kt index 4149cb025c..d0c430a6cb 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResult.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResult.kt @@ -1,8 +1,8 @@ package camp.nextstep.edu.step.step2.domain.result data class LottoResult( - private val lottoTotalPrice: Int, - private val lottoResults: List + val lottoTotalPrice: Int, + val lottoResults: List ) { init { @@ -17,10 +17,4 @@ data class LottoResult( return lottoResults.count { it == lottoMatch } } - companion object { - fun of(lottoTotalPrice: Int, lottoResults: List): LottoResult { - return LottoResult(lottoTotalPrice, lottoResults) - } - } - } From 125967f6010c9e6df355a16504e32843ac7039c0 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Tue, 14 Nov 2023 17:36:39 +0900 Subject: [PATCH 31/92] =?UTF-8?q?refactor=20:=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EC=83=81=EC=A0=90=20(=20LottoStore=20)=20=EB=82=B4=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20=ED=99=95=EC=9D=B8=20=ED=95=A8=EC=88=98=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EC=88=98=EB=9F=89?= =?UTF-8?q?=20=EC=B2=B4=ED=81=AC=20=ED=95=A8=EC=88=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step2/domain/store/LottoStore.kt | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt index aa262df440..a329c654da 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt @@ -1,34 +1,31 @@ package camp.nextstep.edu.step.step2.domain.store import camp.nextstep.edu.step.step2.domain.amount.BuyAmount -import camp.nextstep.edu.step.step2.domain.lotto.Numbers -import camp.nextstep.edu.step.step2.domain.result.LottoMatch +import camp.nextstep.edu.step.step2.domain.lotto.WinningLotto import camp.nextstep.edu.step.step2.domain.result.LottoResult object LottoStore { - private const val LOTTO_TICKET_PRICE = 1000 + /** + * @description : 로또 장당의 가격은 정부에서 정해진 정책만큼 가격이 달라지듯이 해당 미션에서는 각 Store마다 가격이 다르다고 가정했다. + */ + private const val LOTTO_TICKET_PRICE = 1000L /** * @description : 구매금액에 따른 로또 티켓 수량을 구한다. */ fun buyLottoTickets(buyAmount: BuyAmount): LottoTickets { - val lottoTicketAmount = - buyAmount.getAmount().divide(LOTTO_TICKET_PRICE.toBigDecimal()).toInt() + val lottoTicketAmount = buyAmount.divideByLotteryPrice(ticketPrice = LOTTO_TICKET_PRICE) return LottoTickets(lottoTicketAmount) } /** * @description : 로또의 당첨결과르 확인한다. ( 보통 로또의 경우 구매처에서 용지를 넣고 확인하는 방식을 활용했다. ) */ - fun checkLottoTicketsWinningResult( - lottoNumbers: List, - lastWeekNumbers: Numbers - ): LottoResult { - val totalPrice = lottoNumbers.size * LOTTO_TICKET_PRICE - val matchResult = lottoNumbers - .map { numbers -> numbers.countMatch(lastWeekNumbers) } - .map { LottoMatch.of(it) } - .sorted() + fun checkLottoTicketsWinningResult(winningLotto: WinningLotto): LottoResult { + + val totalPrice = + winningLotto.getTotalPriceByLottoAmountAndTicketPrice(ticketPrice = LOTTO_TICKET_PRICE) + val matchResult = winningLotto.getLottoMatchResult() return LottoResult(totalPrice, matchResult) } From cbdf4038cfc38d668550f313057eb5eca4c4daf7 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Tue, 14 Nov 2023 17:37:18 +0900 Subject: [PATCH 32/92] =?UTF-8?q?refactor=20:=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EB=B0=9C=EA=B8=89=20=ED=8B=B0=EC=BC=93=EB=93=A4=20(=20LottoTic?= =?UTF-8?q?kets=20)=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=82=B4,=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=83=9D=EC=84=B1=20=ED=95=A8=EC=88=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20private=20,=20get,=20of=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step/step2/domain/store/LottoTickets.kt | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoTickets.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoTickets.kt index 4f69ecccfc..add496a3ba 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoTickets.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoTickets.kt @@ -1,34 +1,23 @@ package camp.nextstep.edu.step.step2.domain.store -import camp.nextstep.edu.step.step2.domain.lotto.Numbers +import camp.nextstep.edu.step.step2.domain.lotto.Lotto @JvmInline value class LottoTickets( - private val lottoTicketAmount: Int + val lottoTicketAmount: Int ) { init { require(lottoTicketAmount > 0) { "로또 티켓은 1개 이상이어야 합니다." } } - fun getLottoTicketAmount(): Int { - return lottoTicketAmount - } - /** * @description : 로또 티켓 수량에 따른 로또 번호를 생성한다. */ - fun createNumbersByLottoTicketAmount(): List { + fun createNumbersByLottoTicketAmount(): List { return (1..lottoTicketAmount) - .map { Numbers(numbers = Numbers.createNumbers()) } + .map { Lotto.generateAutoNumbers() } .distinct() } - - companion object { - fun of(lottoTicketAmount: Int): LottoTickets { - return LottoTickets(lottoTicketAmount) - } - } - } From 43d26005355784a823a7b0179fa35f5d1060c3be Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Tue, 14 Nov 2023 17:38:36 +0900 Subject: [PATCH 33/92] =?UTF-8?q?refactor=20:=20private,=20of=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=A0=9C=EA=B1=B0=EB=A5=BC=20=ED=86=B5?= =?UTF-8?q?=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nextstep/edu/step/step2/view/InputView.kt | 8 ++-- .../step2/domain/lotto/LottoTicketsTest.kt | 11 +++-- .../edu/step/step2/domain/lotto/NumberTest.kt | 6 +-- .../step2/domain/result/LottoResultTest.kt | 7 ++-- .../step/step2/domain/store/LottoStoreTest.kt | 42 +++++++++++-------- 5 files changed, 39 insertions(+), 35 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt index c85b1ccbd3..c2a9fdb068 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt @@ -1,18 +1,18 @@ package camp.nextstep.edu.step.step2.view import camp.nextstep.edu.step.step2.domain.amount.BuyAmount -import camp.nextstep.edu.step.step2.domain.lotto.Numbers +import camp.nextstep.edu.step.step2.domain.lotto.Lotto class InputView { fun getInputValueAndReturnBuyAmount(): BuyAmount { println("구입금액을 입력해 주세요.") - return BuyAmount.of(readLine()!!.toLong()) + return BuyAmount(readLine()!!.toLong()) } - fun inputLastWeekWinningNumbers(): Numbers { + fun inputLastWeekWinningNumbers(): Lotto { println("지난 주 당첨 번호를 입력해 주세요.") - return Numbers.ofInputValues(numbers = readLine()!!) + return Lotto.ofInputValues(numbers = readLine()!!) } } diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTicketsTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTicketsTest.kt index b712f4f03e..88d94c267b 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTicketsTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTicketsTest.kt @@ -14,22 +14,21 @@ class LottoTicketsTest : BehaviorSpec({ val ticketAmount = 1 When("생성 시") { - val lottoTickets = LottoTickets.of(ticketAmount) + val lottoTickets = LottoTickets(lottoTicketAmount = ticketAmount) Then("주어진 수량만큼의 로또 티켓이 생성된다") { - assertEquals(lottoTickets.getLottoTicketAmount(), 1) + assertEquals(lottoTickets.lottoTicketAmount, 1) } } } Given("로또 티켓이 생성되고") { - val lottoTickets = LottoTickets.of(lottoTicketAmount = 5) + val lottoTickets = LottoTickets(lottoTicketAmount = 5) When("로또 번호 생성시") { val lottoNumbers = lottoTickets.createNumbersByLottoTicketAmount() Then("주어진 티켓 수만큼 로또 번호가 생성된다") { - println(lottoNumbers) assertEquals(lottoNumbers.size, 5) } } @@ -40,7 +39,7 @@ class LottoTicketsTest : BehaviorSpec({ When("생성시") { val lottoTickets = shouldThrow { - LottoTickets.of(lottoTicketAmount = buyAmount) + LottoTickets(lottoTicketAmount = buyAmount) } Then("예외가 발생한다") { @@ -51,7 +50,7 @@ class LottoTicketsTest : BehaviorSpec({ Given("로또 티켓이 주어지고") { val ticketAmount = 1 - val lottoTickets = LottoTickets.of(ticketAmount) + val lottoTickets = LottoTickets(lottoTicketAmount = ticketAmount) When("숫자 생성을 요청하면") { val lottoNumbers = lottoTickets.createNumbersByLottoTicketAmount() diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumberTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumberTest.kt index 20643a34b9..5689e20629 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumberTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumberTest.kt @@ -12,10 +12,10 @@ class NumberTest : BehaviorSpec({ val number = 1 When("생성을 요청하면") { - val lottoNumber = Number.of(number) + val lottoNumber = Number(number = number) Then("주어진 숫자가 생성된다") { - lottoNumber shouldBe Number.of(1) + lottoNumber shouldBe Number(number = 1) } } } @@ -25,7 +25,7 @@ class NumberTest : BehaviorSpec({ When("생성을 요청하면") { val lottoNumber = shouldThrow { - Number.of(number) + Number(number = number) } Then("예외가 발생한다") { diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt index 51a166efde..67646d8a66 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt @@ -13,10 +13,10 @@ class LottoResultTest : BehaviorSpec({ When("로또 결과를 생성하면") { val lottoResult = - LottoResult.of(lottoTotalPrice = totalPrice, lottoResults = matchResult) + LottoResult(lottoTotalPrice = totalPrice, lottoResults = matchResult) Then("로또 결과가 생성된다") { - lottoResult shouldBe LottoResult.of( + lottoResult shouldBe LottoResult( lottoTotalPrice = 1000, lottoResults = listOf(LottoMatch.of(matchCount = 6)) ) @@ -28,8 +28,7 @@ class LottoResultTest : BehaviorSpec({ val totalPrice = 1000 val matchResult = listOf(LottoMatch.of(matchCount = 6)) - val lottoResult = - LottoResult.of(lottoTotalPrice = totalPrice, lottoResults = matchResult) + val lottoResult = LottoResult(lottoTotalPrice = totalPrice, lottoResults = matchResult) When("로또 통계율 계산을 시도하면") { val result = lottoResult.calculateProfitRate() diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt index f17cc7a147..6e22bda305 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt @@ -1,8 +1,9 @@ package camp.nextstep.edu.step.step2.domain.store import camp.nextstep.edu.step.step2.domain.amount.BuyAmount +import camp.nextstep.edu.step.step2.domain.lotto.Lotto import camp.nextstep.edu.step.step2.domain.lotto.Number -import camp.nextstep.edu.step.step2.domain.lotto.Numbers +import camp.nextstep.edu.step.step2.domain.lotto.WinningLotto import camp.nextstep.edu.step.step2.domain.result.LottoMatch import camp.nextstep.edu.step.step2.domain.result.LottoResult import io.kotest.core.spec.style.BehaviorSpec @@ -20,42 +21,47 @@ class LottoStoreTest : BehaviorSpec({ val lottoTickets = LottoStore.buyLottoTickets(buyAmount) Then("구매한 금액만큼의 로또 티켓 수를 반환한다.") { - lottoTickets.getLottoTicketAmount() shouldBe 10 + lottoTickets.lottoTicketAmount shouldBe 10 } } } Given("로또번호와 이전 당첨번호를 입력하게되고") { val lottoNumbers = listOf( - Numbers.ofNumbers( + Lotto( listOf( - Number.of(1), - Number.of(2), - Number.of(3), - Number.of(4), - Number.of(5), - Number.of(6) + Number(number = 1), + Number(number = 2), + Number(number = 3), + Number(number = 4), + Number(number = 5), + Number(number = 6) ) ) ) - val lastWeekWinningLottoNumbers = Numbers.ofNumbers( + val lastWeekWinningLottoLotto = Lotto( listOf( - Number.of(1), - Number.of(2), - Number.of(3), - Number.of(4), - Number.of(5), - Number.of(6) + Number(number = 1), + Number(number = 2), + Number(number = 3), + Number(number = 4), + Number(number = 5), + Number(number = 6) ) ) + val winningLotto = WinningLotto( + userLottoTickets = lottoNumbers, + winningLotto = lastWeekWinningLottoLotto + ) + When("로또 번호를 검증하면") { val lottoResult = - LottoStore.checkLottoTicketsWinningResult(lottoNumbers, lastWeekWinningLottoNumbers) + LottoStore.checkLottoTicketsWinningResult(winningLotto = winningLotto) Then("로또 결과를 반환한다.") { - lottoResult shouldBe LottoResult.of( + lottoResult shouldBe LottoResult( lottoTotalPrice = 1000, lottoResults = listOf( LottoMatch.of( From a9eecfe8c65c9b16ca124bc13fde4290a9f2182b Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Tue, 14 Nov 2023 17:39:11 +0900 Subject: [PATCH 34/92] =?UTF-8?q?refactor=20:=20=EC=B6=9C=EB=A0=A5=20View?= =?UTF-8?q?=20=EB=82=B4,=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20?= =?UTF-8?q?=EB=82=B4=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=B6=80=EB=B6=84=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/nextstep/edu/step/step2/view/OutputView.kt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt index 5b5b54b5ce..a5180c2e8e 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt @@ -1,17 +1,15 @@ package camp.nextstep.edu.step.step2.view -import camp.nextstep.edu.step.step2.domain.lotto.Numbers import camp.nextstep.edu.step.step2.domain.result.LottoMatch import camp.nextstep.edu.step.step2.domain.result.LottoResult -import camp.nextstep.edu.step.step2.domain.store.LottoTickets class OutputView { - fun displayTicketsNumbers(lottoTickets: LottoTickets, ticketNumbers: List) { - println("${lottoTickets.getLottoTicketAmount()}개를 구매했습니다.") + fun displayTicketsNumbers(ticketsAmount: Int, ticketNumbers: List>) { + println("${ticketsAmount}개를 구매했습니다.") for (ticketNumber in ticketNumbers) { - println(ticketNumber.getNumberElements()) + println(ticketNumber) } } @@ -24,4 +22,5 @@ class OutputView { } println("총 수익률은 ${lottoResult.calculateProfitRate()}입니다.") } + } From 1d67b02fe132a1b12ea79b65031481a6e6fc3127 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Tue, 14 Nov 2023 17:39:54 +0900 Subject: [PATCH 35/92] =?UTF-8?q?test=20:=20=EC=9D=B4=EC=A0=84=20Step1=20?= =?UTF-8?q?=EB=82=B4,=20=EC=9D=8C=EC=88=98=20=ED=8F=AC=ED=95=A8=20?= =?UTF-8?q?=EC=8B=9D=20=EA=B4=80=EB=A0=A8=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step/step1/domain/expression/ExpressionTest.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/test/kotlin/camp/nextstep/edu/step/step1/domain/expression/ExpressionTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step1/domain/expression/ExpressionTest.kt index a4c82f5ae7..4d61327de9 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step1/domain/expression/ExpressionTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step1/domain/expression/ExpressionTest.kt @@ -35,4 +35,18 @@ class ExpressionTest : BehaviorSpec({ } } + Given("만약, 식에 음수가 포함되어있고") { + val expressionRequestWithNegativeNumbers = "1,-2:3" + + When("생성을 요청하면") { + val exceptionByNegativeNumber = shouldThrow { + Expression(value = expressionRequestWithNegativeNumbers) + } + + Then("예외가 발생한다.") { + exceptionByNegativeNumber shouldBe RuntimeException() + } + } + } + }) From f14f18b2f63bc78f6b725b7298f2928192fb9c6f Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Tue, 14 Nov 2023 17:40:23 +0900 Subject: [PATCH 36/92] =?UTF-8?q?feat=20:=20=EA=B0=81=20=EC=A0=84=EB=9E=B5?= =?UTF-8?q?=EB=B3=84=20=EC=88=AB=EC=9E=90=20=EC=83=9D=EC=84=B1=EC=9D=84=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20Enum=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step2/generator/NumberGenerator.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt new file mode 100644 index 0000000000..3151e4dddd --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt @@ -0,0 +1,15 @@ +package camp.nextstep.edu.step.step2.generator + +enum class NumberGenerator( + val generate: () -> List +) { + LOTTO_RANDOM({ (1..45).shuffled().subList(0, 6).distinct().sorted() }); + + + companion object { + fun generate(generator: NumberGenerator): List { + return generator.generate() + } + } + +} From 027b1c2903d0841426a5e5249c9edb6c6c0c8615 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Tue, 14 Nov 2023 17:41:00 +0900 Subject: [PATCH 37/92] =?UTF-8?q?test=20:=20=EC=88=AB=EC=9E=90=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EA=B8=B0=20(=20Number=20Generator=20)=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EC=9D=84=20=ED=86=B5=ED=95=9C=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step2/generator/NumberGeneratorTest.kt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/test/kotlin/camp/nextstep/edu/step/step2/generator/NumberGeneratorTest.kt diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/generator/NumberGeneratorTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/generator/NumberGeneratorTest.kt new file mode 100644 index 0000000000..22847762a0 --- /dev/null +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/generator/NumberGeneratorTest.kt @@ -0,0 +1,22 @@ +package camp.nextstep.edu.step.step2.generator + +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.DisplayName + +@DisplayName("번호 생성기는") +class NumberGeneratorTest : BehaviorSpec({ + + Given("각 생성전략이 주어지고") { + val generatorStrategy = NumberGenerator.LOTTO_RANDOM + + When("생성기에 전략을 주입하면") { + val numberGenerator = NumberGenerator.generate(generatorStrategy) + + Then("각 전략에 맞는 번호들이 생성된다.") { + numberGenerator.size shouldBe 6 + } + } + } + +}) From 2ea2f702f4073b6326c03f71fb91dccc6242d340 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Tue, 14 Nov 2023 17:41:22 +0900 Subject: [PATCH 38/92] =?UTF-8?q?refactor=20:=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EC=8B=A4=ED=96=89=20Main=20=ED=95=A8=EC=88=98=20=EB=82=B4,=20?= =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EA=B0=92=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/camp/nextstep/edu/step/step2/main.kt | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt index bafa40c02c..2062438565 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt @@ -1,8 +1,10 @@ package camp.nextstep.edu.step.step2 +import camp.nextstep.edu.step.step2.domain.lotto.WinningLotto import camp.nextstep.edu.step.step2.domain.store.LottoStore import camp.nextstep.edu.step.step2.view.InputView import camp.nextstep.edu.step.step2.view.OutputView +import java.util.stream.Collectors fun main() { val inputView = InputView() @@ -13,16 +15,22 @@ fun main() { val ticketsNumbers = tickets.createNumbersByLottoTicketAmount() + val ticketElements = ticketsNumbers.stream() + .map { it.getNumberElements() } + .collect(Collectors.toList()) + outputView.displayTicketsNumbers( - lottoTickets = tickets, - ticketNumbers = ticketsNumbers + ticketsAmount = tickets.lottoTicketAmount, + ticketNumbers = ticketElements ) val lastWeekWinningNumbers = inputView.inputLastWeekWinningNumbers() val lottoResult = LottoStore.checkLottoTicketsWinningResult( - lottoNumbers = ticketsNumbers, - lastWeekNumbers = lastWeekWinningNumbers + winningLotto = WinningLotto( + userLottoTickets = ticketsNumbers, + winningLotto = lastWeekWinningNumbers + ) ) outputView.displayLottoResult(lottoResult = lottoResult) From a4b41cedfdc7853d7d2229afd7efcea1bd2193d2 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Tue, 14 Nov 2023 17:42:25 +0900 Subject: [PATCH 39/92] =?UTF-8?q?refactor=20:=20Numbers=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EA=B3=BC=20=EC=88=AB=EC=9E=90=20=EC=83=9D=EC=84=B1=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=9D=84=20=ED=86=B5=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lotto/{NumbersTest.kt => LottoTest.kt} | 33 +++---------------- 1 file changed, 5 insertions(+), 28 deletions(-) rename src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/{NumbersTest.kt => LottoTest.kt} (55%) diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumbersTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt similarity index 55% rename from src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumbersTest.kt rename to src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt index ce049067b9..f03810f78e 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumbersTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt @@ -1,12 +1,11 @@ package camp.nextstep.edu.step.step2.domain.lotto -import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe import org.junit.jupiter.api.DisplayName @DisplayName("로또 번호들은") -class NumbersTest : BehaviorSpec({ +class LottoTest : BehaviorSpec({ Given("로또 번호들이 주어지고") { val requestNumbers = listOf( @@ -19,10 +18,10 @@ class NumbersTest : BehaviorSpec({ ) When("생성을 요청하면") { - val numbers = Numbers.ofNumbers(numbers = requestNumbers) + val lotto = Lotto(numbers = requestNumbers) Then("주어진 로또 번호들이 생성된다") { - numbers shouldBe Numbers.ofNumbers( + lotto shouldBe Lotto( numbers = listOf( Number(number = 1), Number(number = 2), @@ -36,35 +35,13 @@ class NumbersTest : BehaviorSpec({ } } - - Given("만약 중복인 숫자가 포함되어 있을 경우") { - val requestNumbers = listOf( - Number(number = 1), - Number(number = 2), - Number(number = 3), - Number(number = 4), - Number(number = 5), - Number(number = 5) - ) - - When("생성을 요청하면") { - val numbers = shouldThrow { - Numbers.ofNumbers(numbers = requestNumbers) - } - - Then("예외가 발생한다") { - numbers.message shouldBe "로또 번호는 중복될 수 없습니다." - } - } - } - Given("로또의 번호들은") { When("새로운 번호 생성 요청이 들어오면") { - val numbers = Numbers.createNumbers() + val lotto = Lotto.generateAutoNumbers() Then("6개의 번호가 생성된다") { - numbers.size shouldBe 6 + lotto.numbers.size shouldBe 6 } } } From 2c4f410b09e62f35be31e35142d518228f681d4c Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Tue, 14 Nov 2023 17:55:51 +0900 Subject: [PATCH 40/92] =?UTF-8?q?docs=20:=20=EC=A0=84=EB=9E=B5=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EB=A6=AC=EB=93=9C?= =?UTF-8?q?=EB=AF=B8=20=EB=82=B4=20=EB=8F=84=EB=A9=94=EC=9D=B8,=20?= =?UTF-8?q?=EA=B3=A0=EB=A0=A4=EC=82=AC=ED=95=AD=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3108b10021..52a3f84121 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,13 @@ # Step2 - 로또 ( Lotto ) ## 도메인 ( Domain ) - 구매금액 ( BuyAmount ) -- 로또 번호 ( LottoNumber ) -- 로또 번호들 ( LottoNumbers ) +- 로또 번호 ( Number ) +- 로또 ( Lotto ) - 일급 컬렉션 - 로또 상점 ( LottoStore ) - 구매한 로또 티켓들 ( LottoTickets ) -- 로또 결과 ( LottoResult ) +- 로또 당첨 확인 ( WinningLotto ) +- 로또 최종 결과 ( LottoResult ) +- 번호생성기 ( NumberGenerator ) ## 고려해야하는 사항 - 구매금액 @@ -29,10 +31,11 @@ - 로또 번호 - 로또 번호는 1 ~ 45 사이의 숫자이다. - 로또 번호는 중복될 수 없다. +- 번호생성기 + - 각 전략을 통해 번호 생성이 가능하다. - 로또 티켓 - 로또 티켓은 구매한 수량만큼 번호가 생성된다. - 로또 결과 - 당첨 내용에 따른 통계 계산이 가능하다. - 이전 당첨번호를 통해 당첨 여부 확인이 가능하다. - 로또의 총 금액은 0보다 커야한다. - From 20e6c26fdf193231d2dc2ebccf50a62eaac6c9ed Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Tue, 14 Nov 2023 17:56:36 +0900 Subject: [PATCH 41/92] =?UTF-8?q?test=20:=20=EB=8B=B9=EC=B2=A8=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20=ED=99=95=EC=9D=B8=20=EB=8F=84=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20,=20=EC=98=88=EC=99=B8,=20=EA=B3=84?= =?UTF-8?q?=EC=82=B0=EA=B8=88=EC=95=A1=20=EC=A1=B0=ED=9A=8C,=20=EB=8B=B9?= =?UTF-8?q?=EC=B2=A8=EB=B2=88=ED=98=B8=20=EC=A1=B0=ED=9A=8C=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=A7=84=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step2/domain/lotto/WinningLottoTest.kt | 202 ++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt new file mode 100644 index 0000000000..94ebf519ba --- /dev/null +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt @@ -0,0 +1,202 @@ +package camp.nextstep.edu.step.step2.domain.lotto + +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.DisplayName + +@DisplayName("당첨 로또 확인 도메인은") +class WinningLottoTest : BehaviorSpec({ + + Given("유저 티켓번호들과 이전 당첨 로또가 주어지고") { + val userLottoTickets = listOf( + Lotto( + listOf( + Number(1), + Number(2), + Number(3), + Number(4), + Number(5), + Number(6) + ) + ) + ) + + val winningLotto = Lotto( + listOf( + Number(1), + Number(2), + Number(3), + Number(4), + Number(5), + Number(6) + ) + ) + + When("생성을 요청하면") { + val winningLotto = WinningLotto( + userLottoTickets = userLottoTickets, + winningLotto = winningLotto + ) + + Then("정상적으로 생성된다.") { + winningLotto.winningLotto shouldBe Lotto( + listOf( + Number(1), + Number(2), + Number(3), + Number(4), + Number(5), + Number(6) + ) + ) + + winningLotto.userLottoTickets shouldBe listOf( + Lotto( + listOf( + Number(1), + Number(2), + Number(3), + Number(4), + Number(5), + Number(6) + ) + ) + ) + } + + } + } + + Given("만약 하나라도 비어있는 값이 존재하면") { + val winningLotto = Lotto( + listOf( + Number(1), + Number(2), + Number(3), + Number(4), + Number(5), + Number(6) + ) + ) + + val emptyUserLotto = emptyList() + + When("생성 시") { + val exceptionByEmptyUserLotto = shouldThrow { + WinningLotto( + userLottoTickets = emptyUserLotto, + winningLotto = winningLotto + ) + } + + Then("예외가 발생한다.") { + exceptionByEmptyUserLotto.message shouldBe "구매한 로또가 없습니다." + } + } + } + + + Given("티켓의 가격이 주어지면") { + val ticketPrice = 1000L + + val userLottoTickets = listOf( + Lotto( + listOf( + Number(1), + Number(2), + Number(3), + Number(4), + Number(5), + Number(6) + ) + ), + Lotto( + listOf( + Number(1), + Number(2), + Number(3), + Number(4), + Number(5), + Number(6) + ) + ) + ) + + val winningLotto = Lotto( + listOf( + Number(1), + Number(2), + Number(3), + Number(4), + Number(5), + Number(6) + ) + ) + + val winningLottoDomain = WinningLotto( + userLottoTickets = userLottoTickets, + winningLotto = winningLotto + ) + + When("총 계산금액 요청 시") { + val totalPrice = winningLottoDomain + .getTotalPriceByLottoAmountAndTicketPrice(ticketPrice = ticketPrice) + + Then("정상적으로 계산된다.") { + totalPrice shouldBe 2000L + } + } + } + + + Given("생성된 상태에서") { + val userLottoTickets = listOf( + Lotto( + listOf( + Number(1), + Number(2), + Number(3), + Number(4), + Number(5), + Number(6) + ) + ), + Lotto( + listOf( + Number(1), + Number(2), + Number(3), + Number(4), + Number(5), + Number(6) + ) + ) + ) + + val winningLotto = Lotto( + listOf( + Number(1), + Number(2), + Number(3), + Number(4), + Number(5), + Number(6) + ) + ) + + val winningLottoDomain = WinningLotto( + userLottoTickets = userLottoTickets, + winningLotto = winningLotto + ) + + When("당첨번호를 조회하게 되면") { + val lottoMatchResult = winningLottoDomain.getLottoMatchResult() + + Then("정상적으로 조회가 가능하다.") { + lottoMatchResult.size shouldBe 2 + } + } + } + +}) From dc3f21d407b9ac3de1fcd788854f04541e379ea2 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Sat, 2 Dec 2023 23:11:59 +0900 Subject: [PATCH 42/92] =?UTF-8?q?refactor=20:=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=82=B4=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4,=20=EB=82=B4=EB=B6=80=20=EB=B9=84=EC=A7=80=EB=8B=88?= =?UTF-8?q?=EC=8A=A4=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit value Class -> Class 수정과 로또 번호 생성 메서드 제거 --- .../edu/step/step2/domain/lotto/Lotto.kt | 30 +++++-------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt index 4d7b878c4c..88839d6171 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt @@ -1,39 +1,23 @@ package camp.nextstep.edu.step.step2.domain.lotto -import camp.nextstep.edu.step.step2.generator.NumberGenerator -import camp.nextstep.edu.step.step2.generator.NumberGenerator.LOTTO_RANDOM - -@JvmInline -value class Lotto( +class Lotto( val numbers: List ) { - fun getNumberElements(): List { - return numbers.map { it.number } + fun countMatch(targetLotto: Lotto): Int { + return numbers.count { targetLotto.numbers.contains(it) } } - fun countMatch(targetLotto: Lotto): Int { - return numbers.count { targetLotto.getNumberElements().contains(it.number) } + fun getNumberElements(): List { + return numbers.map { it.number } } companion object { - fun ofInputValues(numbers: String): Lotto { val numberList = numbers.split(",") .map { it.trim() } - .map { Number(number = it.toInt()) } - return Lotto(numbers = numberList) - } - - /** - * @description : 로또 번호를 자동 생성한다. - */ - fun generateAutoNumbers(): Lotto { - val numbers = NumberGenerator.generate(LOTTO_RANDOM) - - val lottoNums = numbers.map { Number(number = it) } - - return Lotto(numbers = lottoNums) + .map { it.toInt() } + return Lotto(numbers = numberList.map { Number(it) }) } } From 027fca161da32e9b2f513066ff89e38346f94f09 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Sat, 2 Dec 2023 23:12:21 +0900 Subject: [PATCH 43/92] =?UTF-8?q?feat=20:=20Lotto=20Tickets=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=EB=A5=BC=20=EC=9C=84=ED=95=9C=20Lottos=20=EC=9D=BC?= =?UTF-8?q?=EA=B8=89=20=EC=BB=AC=EB=A0=89=EC=85=98=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step2/domain/lotto/Lottos.kt | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lottos.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lottos.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lottos.kt new file mode 100644 index 0000000000..9effa22d0c --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lottos.kt @@ -0,0 +1,23 @@ +package camp.nextstep.edu.step.step2.domain.lotto + +import java.util.stream.Collectors + +class Lottos( + val lottos: List +) { + + init { + require(lottos.isNotEmpty()) { "로또는 1개 이상이어야 합니다." } + } + + fun getLottoElements(): List> { + return lottos.stream() + .map { lotto -> lotto.getNumberElements() } + .collect(Collectors.toList()) + } + + fun getLottoSize(): Int { + return lottos.size + } + +} From 5711a9e8f0095c990e1a6c3798759c9524c28061 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Sat, 2 Dec 2023 23:13:13 +0900 Subject: [PATCH 44/92] =?UTF-8?q?refactor=20:=20=EB=8B=B9=EC=B2=A8=20?= =?UTF-8?q?=EB=A1=9C=EB=98=90=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=82=B4,?= =?UTF-8?q?=20=ED=94=84=EB=A1=9C=ED=8D=BC=ED=8B=B0,=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 유저 티켓 프로퍼티 제거와 당첨 결과 확인 메서드 제거 --- .../edu/step/step2/domain/lotto/WinningLotto.kt | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt index 6a4d5a5b65..82cd6cfee7 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt @@ -1,26 +1,11 @@ package camp.nextstep.edu.step.step2.domain.lotto -import camp.nextstep.edu.step.step2.domain.result.LottoMatch - data class WinningLotto( - val userLottoTickets: List, val winningLotto: Lotto, ) { init { - require(userLottoTickets.isNotEmpty()) { "구매한 로또가 없습니다." } require(winningLotto.numbers.isNotEmpty()) { "당첨번호가 입력되지 않았습니다." } } - fun getTotalPriceByLottoAmountAndTicketPrice(ticketPrice: Long): Int { - return userLottoTickets.size * ticketPrice.toInt() - } - - fun getLottoMatchResult(): List { - return userLottoTickets - .map { numbers -> numbers.countMatch(winningLotto) } - .map { LottoMatch.of(it) } - .sorted() - } - } From 50fca4f59f3d77ee796922761384fc210144a29f Mon Sep 17 00:00:00 2001 From: kimueibin Date: Sat, 2 Dec 2023 23:14:44 +0900 Subject: [PATCH 45/92] =?UTF-8?q?refactor=20:=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EB=8B=B9=EC=B2=A8=20=EA=B2=B0=EA=B3=BC=20=ED=99=95=EC=9D=B8=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95=20(=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8,=20dto=20=EC=83=9D=EC=84=B1,=20main=20,=20ou?= =?UTF-8?q?tput=20view=20)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Result 도메인 내, 결과와 Dto 변환 메서드 추가, 결과전달을 위한 dto 생성, main과 output view 내 결과확인 메서드 수정 --- .../step/step2/domain/result/LottoResult.kt | 26 +++++++++++++++++-- .../edu/step/step2/dto/LottoResultDto.kt | 13 ++++++++++ .../camp/nextstep/edu/step/step2/main.kt | 11 +++----- .../edu/step/step2/view/OutputView.kt | 12 ++++----- 4 files changed, 46 insertions(+), 16 deletions(-) create mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/dto/LottoResultDto.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResult.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResult.kt index d0c430a6cb..9f7f0f9537 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResult.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResult.kt @@ -1,5 +1,7 @@ package camp.nextstep.edu.step.step2.domain.result +import camp.nextstep.edu.step.step2.dto.LottoResultDto + data class LottoResult( val lottoTotalPrice: Int, val lottoResults: List @@ -9,11 +11,31 @@ data class LottoResult( require(lottoTotalPrice > 0) { "로또의 총 금액은 0보다 커야합니다." } } - fun calculateProfitRate(): Double { + /** + * @description : Lotto Match 결과를 토대로 OutputView에 전달할 LottoResultDto를 생성합니다. + */ + fun calculateResultAndReturnDto(): LottoResultDto { + LottoMatch.values().reversed().associateWith { lottoMatch -> + getResultCount(lottoMatch) + }.let { matchCount -> + return LottoResultDto( + matchResponse = matchCount.map { (lottoMatch, count) -> + LottoResultDto.MatchResponse( + lottoMatch.matchCount, + lottoMatch.prize, + count + ) + }, + lottoProfitRate = calculateProfitRate() + ) + } + } + + private fun calculateProfitRate(): Double { return lottoResults.sumOf { it.prize }.toDouble() / lottoTotalPrice } - fun getResultCount(lottoMatch: LottoMatch): Int { + private fun getResultCount(lottoMatch: LottoMatch): Int { return lottoResults.count { it == lottoMatch } } diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/dto/LottoResultDto.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/dto/LottoResultDto.kt new file mode 100644 index 0000000000..f8f13e8ae4 --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/dto/LottoResultDto.kt @@ -0,0 +1,13 @@ +package camp.nextstep.edu.step.step2.dto + +data class LottoResultDto ( + val matchResponse: List, + val lottoProfitRate: Double + ) { + + data class MatchResponse( + val matchCount: Int, + val prize: Int, + val userMatchCont: Int + ) +} diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt index 2062438565..3e983c9d03 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt @@ -4,7 +4,6 @@ import camp.nextstep.edu.step.step2.domain.lotto.WinningLotto import camp.nextstep.edu.step.step2.domain.store.LottoStore import camp.nextstep.edu.step.step2.view.InputView import camp.nextstep.edu.step.step2.view.OutputView -import java.util.stream.Collectors fun main() { val inputView = InputView() @@ -13,11 +12,9 @@ fun main() { val buyAmount = inputView.getInputValueAndReturnBuyAmount() val tickets = LottoStore.buyLottoTickets(buyAmount = buyAmount) - val ticketsNumbers = tickets.createNumbersByLottoTicketAmount() + val lottos = LottoStore.createNumbersByLottoTicketAmount(ticketAmount = tickets) - val ticketElements = ticketsNumbers.stream() - .map { it.getNumberElements() } - .collect(Collectors.toList()) + val ticketElements = lottos.getLottoElements() outputView.displayTicketsNumbers( ticketsAmount = tickets.lottoTicketAmount, @@ -27,11 +24,11 @@ fun main() { val lastWeekWinningNumbers = inputView.inputLastWeekWinningNumbers() val lottoResult = LottoStore.checkLottoTicketsWinningResult( + userLottos = lottos, winningLotto = WinningLotto( - userLottoTickets = ticketsNumbers, winningLotto = lastWeekWinningNumbers ) ) - outputView.displayLottoResult(lottoResult = lottoResult) + outputView.displayLottoResultByDto(lottoResultDto = lottoResult.calculateResultAndReturnDto()) } diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt index a5180c2e8e..600fe136ec 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt @@ -1,7 +1,6 @@ package camp.nextstep.edu.step.step2.view -import camp.nextstep.edu.step.step2.domain.result.LottoMatch -import camp.nextstep.edu.step.step2.domain.result.LottoResult +import camp.nextstep.edu.step.step2.dto.LottoResultDto class OutputView { @@ -13,14 +12,13 @@ class OutputView { } } - fun displayLottoResult(lottoResult: LottoResult) { + fun displayLottoResultByDto(lottoResultDto: LottoResultDto) { println("당첨 통계") println("---------") - LottoMatch.values().reversed().forEach { - val count = lottoResult.getResultCount(it) - println("${it.matchCount}개 일치 (${it.prize}원) - ${count}개") + lottoResultDto.matchResponse.forEach { matchResponse -> + println("${matchResponse.matchCount}개 일치 (${matchResponse.prize}원) - ${matchResponse.userMatchCont}개") } - println("총 수익률은 ${lottoResult.calculateProfitRate()}입니다.") + println("총 수익률은 ${lottoResultDto.lottoProfitRate}입니다.") } } From 975f55629c7fb81798ed0d27d5616ae9de139b10 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Sat, 2 Dec 2023 23:15:34 +0900 Subject: [PATCH 46/92] =?UTF-8?q?refactor=20:=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=ED=8B=B0=EC=BC=93=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 네이밍 수정 ( LottoTicket -> LottoTicketAmount ) , 번호 생성 메서드 제거 --- .../step2/domain/store/LottoTicketAmount.kt | 12 ++++++++++ .../step/step2/domain/store/LottoTickets.kt | 23 ------------------- 2 files changed, 12 insertions(+), 23 deletions(-) create mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoTicketAmount.kt delete mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoTickets.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoTicketAmount.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoTicketAmount.kt new file mode 100644 index 0000000000..c0f6f301e1 --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoTicketAmount.kt @@ -0,0 +1,12 @@ +package camp.nextstep.edu.step.step2.domain.store + +@JvmInline +value class LottoTicketAmount( + val lottoTicketAmount: Int +) { + + init { + require(lottoTicketAmount > 0) { "로또 티켓은 1개 이상이어야 합니다." } + } + +} diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoTickets.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoTickets.kt deleted file mode 100644 index add496a3ba..0000000000 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoTickets.kt +++ /dev/null @@ -1,23 +0,0 @@ -package camp.nextstep.edu.step.step2.domain.store - -import camp.nextstep.edu.step.step2.domain.lotto.Lotto - -@JvmInline -value class LottoTickets( - val lottoTicketAmount: Int -) { - - init { - require(lottoTicketAmount > 0) { "로또 티켓은 1개 이상이어야 합니다." } - } - - /** - * @description : 로또 티켓 수량에 따른 로또 번호를 생성한다. - */ - fun createNumbersByLottoTicketAmount(): List { - return (1..lottoTicketAmount) - .map { Lotto.generateAutoNumbers() } - .distinct() - } - -} From afc59b8a74881a70fa35201df6e6baf3ba04e9be Mon Sep 17 00:00:00 2001 From: kimueibin Date: Sat, 2 Dec 2023 23:16:56 +0900 Subject: [PATCH 47/92] =?UTF-8?q?refactor=20:=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EC=83=81=EC=A0=90=20(=20Lotto=20Store=20)=20=EB=82=B4,=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=EB=90=9C=20=EB=8F=84=EB=A9=94=EC=9D=B8?= =?UTF-8?q?=EB=93=A4=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 결과확인, 금액 확인, 번호생성과 수량 체크 추가 및 수정 진행 --- .../edu/step/step2/domain/store/LottoStore.kt | 63 +++++++++++++++++-- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt index a329c654da..b5687dab56 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt @@ -1,10 +1,18 @@ package camp.nextstep.edu.step.step2.domain.store import camp.nextstep.edu.step.step2.domain.amount.BuyAmount +import camp.nextstep.edu.step.step2.domain.lotto.Lotto +import camp.nextstep.edu.step.step2.domain.lotto.Lottos import camp.nextstep.edu.step.step2.domain.lotto.WinningLotto +import camp.nextstep.edu.step.step2.domain.result.LottoMatch import camp.nextstep.edu.step.step2.domain.result.LottoResult +import camp.nextstep.edu.step.step2.generator.NumberGenerator object LottoStore { + + private const val START_NUMBER = 1 + private const val END_NUMBER = 45 + /** * @description : 로또 장당의 가격은 정부에서 정해진 정책만큼 가격이 달라지듯이 해당 미션에서는 각 Store마다 가격이 다르다고 가정했다. */ @@ -13,21 +21,64 @@ object LottoStore { /** * @description : 구매금액에 따른 로또 티켓 수량을 구한다. */ - fun buyLottoTickets(buyAmount: BuyAmount): LottoTickets { + fun buyLottoTickets(buyAmount: BuyAmount): LottoTicketAmount { val lottoTicketAmount = buyAmount.divideByLotteryPrice(ticketPrice = LOTTO_TICKET_PRICE) - return LottoTickets(lottoTicketAmount) + return LottoTicketAmount(lottoTicketAmount) + } + + /** + * @description : 로또 티켓 수량에 따른 로또 번호를 생성한다. + */ + fun createNumbersByLottoTicketAmount(ticketAmount: LottoTicketAmount): Lottos { + val lottoTickets = mutableListOf() + + for (i in 1..ticketAmount.lottoTicketAmount) { + val numbers = NumberGenerator.generate(NumberGenerator.LOTTO_RANDOM, START_NUMBER, END_NUMBER) + lottoTickets.add(Lotto(numbers = numbers)) + } + + return Lottos(lottos = lottoTickets) } /** * @description : 로또의 당첨결과르 확인한다. ( 보통 로또의 경우 구매처에서 용지를 넣고 확인하는 방식을 활용했다. ) */ - fun checkLottoTicketsWinningResult(winningLotto: WinningLotto): LottoResult { + fun checkLottoTicketsWinningResult( + userLottos: Lottos, + winningLotto: WinningLotto + ): LottoResult { + + val totalPrice = getTotalPriceByLottoAmountAndTicketPrice( + lottoSize = userLottos.getLottoSize(), + ticketPrice = LOTTO_TICKET_PRICE + ) - val totalPrice = - winningLotto.getTotalPriceByLottoAmountAndTicketPrice(ticketPrice = LOTTO_TICKET_PRICE) - val matchResult = winningLotto.getLottoMatchResult() + val matchResult = lottoWinningResults( + userlottos = userLottos, + winningWinningLotto = winningLotto + ) return LottoResult(totalPrice, matchResult) } + /** + * @description : 로또의 수량과 가격을 곱하여 총 금액을 구한다. ( 로또 판매처에서 해당 책임이 부여가 되어야한다고 생각했다. ) + */ + private fun getTotalPriceByLottoAmountAndTicketPrice(lottoSize: Int, ticketPrice: Long): Int { + return lottoSize * ticketPrice.toInt() + } + + /** + * @description : 로또의 결과를 확인합니다. ( 보통 로또 판매처에 내가 구매한 로또들을 넣고 확인하는 방식을 생각했다. ) + */ + private fun lottoWinningResults( + userlottos: Lottos, + winningWinningLotto: WinningLotto + ): List { + return userlottos.lottos + .map { numbers -> numbers.countMatch(winningWinningLotto.winningLotto) } + .map { LottoMatch.of(it) } + .sorted() + } + } From 1feb8b9d8382a70c2ab1d31c8f17e51f0db133a8 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Sat, 2 Dec 2023 23:17:16 +0900 Subject: [PATCH 48/92] =?UTF-8?q?refactor=20:=20=EB=B2=88=ED=98=B8=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20Enum=20=EB=82=B4,=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step2/generator/NumberGenerator.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt index 3151e4dddd..9bb5daaf73 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt @@ -1,14 +1,16 @@ package camp.nextstep.edu.step.step2.generator +import camp.nextstep.edu.step.step2.domain.lotto.Number + enum class NumberGenerator( - val generate: () -> List + val generate: (Int, Int) -> List ) { - LOTTO_RANDOM({ (1..45).shuffled().subList(0, 6).distinct().sorted() }); + LOTTO_RANDOM({ startNum, endNum -> (startNum..endNum).shuffled().subList(0, 6).distinct().sorted() }); companion object { - fun generate(generator: NumberGenerator): List { - return generator.generate() + fun generate(generator: NumberGenerator, startNumber: Int, endNumber: Int): List { + return generator.generate(startNumber, endNumber).map { Number(it) } } } From 1de3c4e367283de54daaf6304f810d27e68cdee3 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Sat, 2 Dec 2023 23:44:09 +0900 Subject: [PATCH 49/92] =?UTF-8?q?refactor=20:=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EB=90=9C=20=EB=8F=84=EB=A9=94=EC=9D=B8=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=A5=B8,=20Lotto,=20Winning=20Lotto,=20Number=20Generator=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step2/domain/lotto/LottoTest.kt | 27 +-- .../step2/domain/lotto/LottoTicketsTest.kt | 37 +--- .../step2/domain/lotto/WinningLottoTest.kt | 170 ++---------------- .../step2/generator/NumberGeneratorTest.kt | 2 +- 4 files changed, 28 insertions(+), 208 deletions(-) diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt index f03810f78e..00ada13892 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt @@ -21,29 +21,16 @@ class LottoTest : BehaviorSpec({ val lotto = Lotto(numbers = requestNumbers) Then("주어진 로또 번호들이 생성된다") { - lotto shouldBe Lotto( - numbers = listOf( - Number(number = 1), - Number(number = 2), - Number(number = 3), - Number(number = 4), - Number(number = 5), - Number(number = 6) - ) + lotto.numbers shouldBe listOf( + Number(number = 1), + Number(number = 2), + Number(number = 3), + Number(number = 4), + Number(number = 5), + Number(number = 6) ) } } } - Given("로또의 번호들은") { - - When("새로운 번호 생성 요청이 들어오면") { - val lotto = Lotto.generateAutoNumbers() - - Then("6개의 번호가 생성된다") { - lotto.numbers.size shouldBe 6 - } - } - } - }) diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTicketsTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTicketsTest.kt index 88d94c267b..5e58da0887 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTicketsTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTicketsTest.kt @@ -1,6 +1,6 @@ package camp.nextstep.edu.step.step2.domain.lotto -import camp.nextstep.edu.step.step2.domain.store.LottoTickets +import camp.nextstep.edu.step.step2.domain.store.LottoTicketAmount import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe @@ -14,22 +14,10 @@ class LottoTicketsTest : BehaviorSpec({ val ticketAmount = 1 When("생성 시") { - val lottoTickets = LottoTickets(lottoTicketAmount = ticketAmount) + val lottoTicketAmount = LottoTicketAmount(lottoTicketAmount = ticketAmount) Then("주어진 수량만큼의 로또 티켓이 생성된다") { - assertEquals(lottoTickets.lottoTicketAmount, 1) - } - } - } - - Given("로또 티켓이 생성되고") { - val lottoTickets = LottoTickets(lottoTicketAmount = 5) - - When("로또 번호 생성시") { - val lottoNumbers = lottoTickets.createNumbersByLottoTicketAmount() - - Then("주어진 티켓 수만큼 로또 번호가 생성된다") { - assertEquals(lottoNumbers.size, 5) + assertEquals(lottoTicketAmount.lottoTicketAmount, 1) } } } @@ -38,25 +26,12 @@ class LottoTicketsTest : BehaviorSpec({ val buyAmount = 0 When("생성시") { - val lottoTickets = shouldThrow { - LottoTickets(lottoTicketAmount = buyAmount) + val lottoTicketAmount = shouldThrow { + LottoTicketAmount(lottoTicketAmount = buyAmount) } Then("예외가 발생한다") { - lottoTickets.message shouldBe "로또 티켓은 1개 이상이어야 합니다." - } - } - } - - Given("로또 티켓이 주어지고") { - val ticketAmount = 1 - val lottoTickets = LottoTickets(lottoTicketAmount = ticketAmount) - - When("숫자 생성을 요청하면") { - val lottoNumbers = lottoTickets.createNumbersByLottoTicketAmount() - - Then("구매 수량만큼 로또번호가 생성된다.") { - lottoNumbers.size shouldBe 1 + lottoTicketAmount.message shouldBe "로또 티켓은 1개 이상이어야 합니다." } } } diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt index 94ebf519ba..a53a21180a 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt @@ -9,20 +9,7 @@ import org.junit.jupiter.api.DisplayName class WinningLottoTest : BehaviorSpec({ Given("유저 티켓번호들과 이전 당첨 로또가 주어지고") { - val userLottoTickets = listOf( - Lotto( - listOf( - Number(1), - Number(2), - Number(3), - Number(4), - Number(5), - Number(6) - ) - ) - ) - - val winningLotto = Lotto( + val winningLottoRequest = Lotto( listOf( Number(1), Number(2), @@ -35,33 +22,17 @@ class WinningLottoTest : BehaviorSpec({ When("생성을 요청하면") { val winningLotto = WinningLotto( - userLottoTickets = userLottoTickets, - winningLotto = winningLotto + winningLotto = winningLottoRequest ) Then("정상적으로 생성된다.") { - winningLotto.winningLotto shouldBe Lotto( - listOf( - Number(1), - Number(2), - Number(3), - Number(4), - Number(5), - Number(6) - ) - ) - - winningLotto.userLottoTickets shouldBe listOf( - Lotto( - listOf( - Number(1), - Number(2), - Number(3), - Number(4), - Number(5), - Number(6) - ) - ) + winningLotto.winningLotto.numbers shouldBe listOf( + Number(1), + Number(2), + Number(3), + Number(4), + Number(5), + Number(6) ) } @@ -69,132 +40,19 @@ class WinningLottoTest : BehaviorSpec({ } Given("만약 하나라도 비어있는 값이 존재하면") { - val winningLotto = Lotto( - listOf( - Number(1), - Number(2), - Number(3), - Number(4), - Number(5), - Number(6) - ) + val emptyLotto = Lotto( + listOf() ) - val emptyUserLotto = emptyList() - When("생성 시") { - val exceptionByEmptyUserLotto = shouldThrow { + val exceptionByEmptyLotto = shouldThrow { WinningLotto( - userLottoTickets = emptyUserLotto, - winningLotto = winningLotto + winningLotto = emptyLotto ) } Then("예외가 발생한다.") { - exceptionByEmptyUserLotto.message shouldBe "구매한 로또가 없습니다." - } - } - } - - - Given("티켓의 가격이 주어지면") { - val ticketPrice = 1000L - - val userLottoTickets = listOf( - Lotto( - listOf( - Number(1), - Number(2), - Number(3), - Number(4), - Number(5), - Number(6) - ) - ), - Lotto( - listOf( - Number(1), - Number(2), - Number(3), - Number(4), - Number(5), - Number(6) - ) - ) - ) - - val winningLotto = Lotto( - listOf( - Number(1), - Number(2), - Number(3), - Number(4), - Number(5), - Number(6) - ) - ) - - val winningLottoDomain = WinningLotto( - userLottoTickets = userLottoTickets, - winningLotto = winningLotto - ) - - When("총 계산금액 요청 시") { - val totalPrice = winningLottoDomain - .getTotalPriceByLottoAmountAndTicketPrice(ticketPrice = ticketPrice) - - Then("정상적으로 계산된다.") { - totalPrice shouldBe 2000L - } - } - } - - - Given("생성된 상태에서") { - val userLottoTickets = listOf( - Lotto( - listOf( - Number(1), - Number(2), - Number(3), - Number(4), - Number(5), - Number(6) - ) - ), - Lotto( - listOf( - Number(1), - Number(2), - Number(3), - Number(4), - Number(5), - Number(6) - ) - ) - ) - - val winningLotto = Lotto( - listOf( - Number(1), - Number(2), - Number(3), - Number(4), - Number(5), - Number(6) - ) - ) - - val winningLottoDomain = WinningLotto( - userLottoTickets = userLottoTickets, - winningLotto = winningLotto - ) - - When("당첨번호를 조회하게 되면") { - val lottoMatchResult = winningLottoDomain.getLottoMatchResult() - - Then("정상적으로 조회가 가능하다.") { - lottoMatchResult.size shouldBe 2 + exceptionByEmptyLotto.message shouldBe "당첨번호가 입력되지 않았습니다." } } } diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/generator/NumberGeneratorTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/generator/NumberGeneratorTest.kt index 22847762a0..f2af06f9f1 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/generator/NumberGeneratorTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/generator/NumberGeneratorTest.kt @@ -11,7 +11,7 @@ class NumberGeneratorTest : BehaviorSpec({ val generatorStrategy = NumberGenerator.LOTTO_RANDOM When("생성기에 전략을 주입하면") { - val numberGenerator = NumberGenerator.generate(generatorStrategy) + val numberGenerator = NumberGenerator.generate(generatorStrategy, startNumber = 1, endNumber = 45) Then("각 전략에 맞는 번호들이 생성된다.") { numberGenerator.size shouldBe 6 From 8e45867588cebe2d498bd3b180392f63e35841b4 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Sat, 2 Dec 2023 23:44:30 +0900 Subject: [PATCH 50/92] =?UTF-8?q?test=20:=20=EB=A1=9C=EB=98=90=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=82=B4=20Dto=20?= =?UTF-8?q?=EB=B3=80=ED=99=98=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step/step2/domain/result/LottoResultTest.kt | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt index 67646d8a66..cffb11db6c 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt @@ -24,18 +24,19 @@ class LottoResultTest : BehaviorSpec({ } } - Given("로또 결과 객체가 주어지고") { + Given("로또 결과 도메인이 주어지고") { val totalPrice = 1000 - val matchResult = listOf(LottoMatch.of(matchCount = 6)) - + val matchResult = listOf(LottoMatch.of(matchCount = 1)) val lottoResult = LottoResult(lottoTotalPrice = totalPrice, lottoResults = matchResult) - When("로또 통계율 계산을 시도하면") { - val result = lottoResult.calculateProfitRate() + When("로또 결과 전달을 위한 Dto를 생성하면") { + val lottoResultDto = lottoResult.calculateResultAndReturnDto() - Then("로또 통계율이 계산된다") { - result shouldBe 2000000.0 - } + Then("로또 결과 Dto가 반환된다") { + lottoResultDto.matchResponse.size shouldBe 5 + lottoResultDto.lottoProfitRate shouldBe 0.0 + } } } + }) From 60d711287b49837f9e4070843aaf0ed64df9a1a1 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Sat, 2 Dec 2023 23:45:06 +0900 Subject: [PATCH 51/92] =?UTF-8?q?test=20:=20=EB=A1=9C=EB=98=90=20=EC=83=81?= =?UTF-8?q?=EC=A0=90=20=EB=82=B4=20=EB=A1=9C=EB=98=90=20=EB=B0=9C=EA=B8=89?= =?UTF-8?q?=20=EB=B0=8F=20=EA=B2=B0=EA=B3=BC=ED=99=95=EC=9D=B8=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step/step2/domain/store/LottoStoreTest.kt | 68 ++++++++++++++++++- 1 file changed, 65 insertions(+), 3 deletions(-) diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt index 6e22bda305..c82d3b3c3d 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt @@ -1,8 +1,9 @@ package camp.nextstep.edu.step.step2.domain.store import camp.nextstep.edu.step.step2.domain.amount.BuyAmount -import camp.nextstep.edu.step.step2.domain.lotto.Lotto import camp.nextstep.edu.step.step2.domain.lotto.Number +import camp.nextstep.edu.step.step2.domain.lotto.Lotto +import camp.nextstep.edu.step.step2.domain.lotto.Lottos import camp.nextstep.edu.step.step2.domain.lotto.WinningLotto import camp.nextstep.edu.step.step2.domain.result.LottoMatch import camp.nextstep.edu.step.step2.domain.result.LottoResult @@ -40,6 +41,8 @@ class LottoStoreTest : BehaviorSpec({ ) ) + val userLottos = Lottos(lottos = lottoNumbers) + val lastWeekWinningLottoLotto = Lotto( listOf( Number(number = 1), @@ -52,13 +55,12 @@ class LottoStoreTest : BehaviorSpec({ ) val winningLotto = WinningLotto( - userLottoTickets = lottoNumbers, winningLotto = lastWeekWinningLottoLotto ) When("로또 번호를 검증하면") { val lottoResult = - LottoStore.checkLottoTicketsWinningResult(winningLotto = winningLotto) + LottoStore.checkLottoTicketsWinningResult(userLottos = userLottos, winningLotto = winningLotto) Then("로또 결과를 반환한다.") { lottoResult shouldBe LottoResult( @@ -72,4 +74,64 @@ class LottoStoreTest : BehaviorSpec({ } } } + + Given("로또의 수량이주어지고") { + val lottoTicketAmount = LottoTicketAmount(lottoTicketAmount = 10) + + When("로또 발급을 시도하면") { + val lottoTickets = LottoStore.createNumbersByLottoTicketAmount(ticketAmount = lottoTicketAmount) + + Then("구매한 수량만큼의 로또가 발급된다.") { + lottoTickets.lottos.size shouldBe 10 + } + } + } + + Given("유저의 로또와 저번주 당첨번호가 주어지고") { + val userLottos = Lottos( + lottos = listOf( + Lotto( + listOf( + Number(number = 1), + Number(number = 2), + Number(number = 3), + Number(number = 4), + Number(number = 5), + Number(number = 6) + ) + ) + ) + ) + + val lastWeekWinningLottoLotto = Lotto( + listOf( + Number(number = 1), + Number(number = 2), + Number(number = 3), + Number(number = 4), + Number(number = 5), + Number(number = 6) + ) + ) + + val winningLotto = WinningLotto( + winningLotto = lastWeekWinningLottoLotto + ) + + When("당첨 결과를 확인하면") { + val lottoResult = LottoStore.checkLottoTicketsWinningResult(userLottos = userLottos, winningLotto = winningLotto) + + Then("당첨 결과를 반환한다.") { + lottoResult shouldBe LottoResult( + lottoTotalPrice = 1000, + lottoResults = listOf( + LottoMatch.of( + matchCount = 6 + ) + ) + ) + } + } + } + }) From 1c01633b62bd718136e3e4487e0672ef97cd0c94 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Tue, 5 Dec 2023 00:33:41 +0900 Subject: [PATCH 52/92] =?UTF-8?q?chore=20:=20Number=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=9D=B4=EB=8F=99=20?= =?UTF-8?q?(=20Lotto=20->=20Number=20)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt | 2 ++ .../nextstep/edu/step/step2/domain/{lotto => number}/Number.kt | 2 +- .../camp/nextstep/edu/step/step2/generator/NumberGenerator.kt | 2 +- .../camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt | 1 + .../nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt | 1 + .../edu/step/step2/domain/{lotto => number}/NumberTest.kt | 3 ++- .../nextstep/edu/step/step2/domain/store/LottoStoreTest.kt | 2 +- 7 files changed, 9 insertions(+), 4 deletions(-) rename src/main/kotlin/camp/nextstep/edu/step/step2/domain/{lotto => number}/Number.kt (76%) rename src/test/kotlin/camp/nextstep/edu/step/step2/domain/{lotto => number}/NumberTest.kt (90%) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt index 88839d6171..22aebc2763 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt @@ -1,5 +1,7 @@ package camp.nextstep.edu.step.step2.domain.lotto +import camp.nextstep.edu.step.step2.domain.number.Number + class Lotto( val numbers: List ) { diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Number.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/Number.kt similarity index 76% rename from src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Number.kt rename to src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/Number.kt index 858c08f577..ecc149f579 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Number.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/Number.kt @@ -1,4 +1,4 @@ -package camp.nextstep.edu.step.step2.domain.lotto +package camp.nextstep.edu.step.step2.domain.number @JvmInline value class Number( diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt index 9bb5daaf73..c89716b3f9 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt @@ -1,6 +1,6 @@ package camp.nextstep.edu.step.step2.generator -import camp.nextstep.edu.step.step2.domain.lotto.Number +import camp.nextstep.edu.step.step2.domain.number.Number enum class NumberGenerator( val generate: (Int, Int) -> List diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt index 00ada13892..9995796252 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt @@ -1,5 +1,6 @@ package camp.nextstep.edu.step.step2.domain.lotto +import camp.nextstep.edu.step.step2.domain.number.Number import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe import org.junit.jupiter.api.DisplayName diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt index a53a21180a..b79e779de7 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt @@ -1,5 +1,6 @@ package camp.nextstep.edu.step.step2.domain.lotto +import camp.nextstep.edu.step.step2.domain.number.Number import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumberTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/NumberTest.kt similarity index 90% rename from src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumberTest.kt rename to src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/NumberTest.kt index 5689e20629..90b2e21693 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumberTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/NumberTest.kt @@ -1,5 +1,6 @@ -package camp.nextstep.edu.step.step2.domain.lotto +package camp.nextstep.edu.step.step2.domain.number +import camp.nextstep.edu.step.step2.domain.number.Number import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt index c82d3b3c3d..f5ca5e8c4d 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt @@ -1,7 +1,7 @@ package camp.nextstep.edu.step.step2.domain.store import camp.nextstep.edu.step.step2.domain.amount.BuyAmount -import camp.nextstep.edu.step.step2.domain.lotto.Number +import camp.nextstep.edu.step.step2.domain.number.Number import camp.nextstep.edu.step.step2.domain.lotto.Lotto import camp.nextstep.edu.step.step2.domain.lotto.Lottos import camp.nextstep.edu.step.step2.domain.lotto.WinningLotto From d89078fe7322c0e9229951edd5f1a8a04f681c23 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Wed, 6 Dec 2023 02:10:27 +0900 Subject: [PATCH 53/92] =?UTF-8?q?feat=20:=20=EB=B3=B4=EB=84=88=EC=8A=A4=20?= =?UTF-8?q?=EC=88=AB=EC=9E=90=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step2/domain/number/BonusNumber.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumber.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumber.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumber.kt new file mode 100644 index 0000000000..76c67e53d8 --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumber.kt @@ -0,0 +1,12 @@ +package camp.nextstep.edu.step.step2.domain.number + + +class BonusNumber( + val number: Number +) { + + fun getNumberElement(): Int { + return number.number + } + +} From f4b3789956085622dff1e680208db936671595d8 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Wed, 6 Dec 2023 02:10:57 +0900 Subject: [PATCH 54/92] =?UTF-8?q?refactor=20:=20=EB=B3=B4=EB=84=88?= =?UTF-8?q?=EC=8A=A4=20=EC=88=AB=EC=9E=90=20=EA=B2=80=EC=A6=9D=EC=9D=84=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20Match=20Enum=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step2/domain/result/LottoMatch.kt | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoMatch.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoMatch.kt index 99644e4d95..73446ecc0c 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoMatch.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoMatch.kt @@ -2,18 +2,20 @@ package camp.nextstep.edu.step.step2.domain.result enum class LottoMatch( val matchCount: Int, + val bonusMatch: Int, val prize: Int ) { - SIX_MATCH(6, 2_000_000_000), - FIVE_MATCH(5, 1_500_000), - FOUR_MATCH(4, 50_000), - THREE_MATCH(3, 5_000), - NONE(0, 0); + SIX_MATCH(6, 0, 2_000_000_000), + FIVE_MATCH(5, 0, 1_500_000), + FIVE_MATCH_WITH_BONUS(5, 1, 30_000_000), + FOUR_MATCH(4, 0,50_000), + THREE_MATCH(3, 0,5_000), + NONE(0, 0,0); companion object { - fun of(matchCount: Int): LottoMatch { - return values().find { it.matchCount == matchCount } ?: NONE + fun of(matchCount: Int, bonusMatch: Int): LottoMatch { + return values().find { it.matchCount == matchCount && it.bonusMatch == bonusMatch } ?: NONE } } } From bba626661ae6c89547be656a474165a462584d82 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Wed, 6 Dec 2023 02:12:18 +0900 Subject: [PATCH 55/92] =?UTF-8?q?refactor=20:=20Lotto=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=82=B4,=20=EB=B3=B4=EB=84=88=EC=8A=A4=20?= =?UTF-8?q?=EC=88=AB=EC=9E=90=20=EA=B2=80=EC=A6=9D=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20count=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt index 22aebc2763..481d7015ad 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt @@ -1,5 +1,6 @@ package camp.nextstep.edu.step.step2.domain.lotto +import camp.nextstep.edu.step.step2.domain.number.BonusNumber import camp.nextstep.edu.step.step2.domain.number.Number class Lotto( @@ -10,6 +11,10 @@ class Lotto( return numbers.count { targetLotto.numbers.contains(it) } } + fun countMatchBonus(bonusNumber: BonusNumber): Int { + return numbers.count { it.number == bonusNumber.getNumberElement() } + } + fun getNumberElements(): List { return numbers.map { it.number } } From 9cbdfd270711c9c0715c5b4e2cdff7b9ecfdaefa Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Wed, 6 Dec 2023 02:12:55 +0900 Subject: [PATCH 56/92] =?UTF-8?q?refactor=20:=20=EA=B2=B0=EA=B3=BC=20?= =?UTF-8?q?=EB=A1=9C=EB=98=90=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=82=B4=20?= =?UTF-8?q?=EB=B3=B4=EB=84=88=EC=8A=A4=20=EC=88=AB=EC=9E=90=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt index 82cd6cfee7..b5155c1dfe 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt @@ -1,7 +1,10 @@ package camp.nextstep.edu.step.step2.domain.lotto +import camp.nextstep.edu.step.step2.domain.number.BonusNumber + data class WinningLotto( val winningLotto: Lotto, + val bonusNumber: BonusNumber ) { init { From 6ea82ead8f1072d92fca5e1cce31945e5cc5b874 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Wed, 6 Dec 2023 02:13:46 +0900 Subject: [PATCH 57/92] =?UTF-8?q?refactor=20:=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EC=83=81=EC=A0=90=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=82=B4=20?= =?UTF-8?q?=EC=96=B4=EC=83=89=ED=95=9C=20=EB=B3=80=EC=88=98=EB=AA=85=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EA=B2=B0=EA=B3=BC=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit winningWinningLotto -> winningLotto 로 수정 --- .../edu/step/step2/domain/store/LottoStore.kt | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt index b5687dab56..729b10bf9b 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt @@ -55,7 +55,7 @@ object LottoStore { val matchResult = lottoWinningResults( userlottos = userLottos, - winningWinningLotto = winningLotto + winningLotto = winningLotto ) return LottoResult(totalPrice, matchResult) @@ -73,12 +73,17 @@ object LottoStore { */ private fun lottoWinningResults( userlottos: Lottos, - winningWinningLotto: WinningLotto + winningLotto: WinningLotto ): List { - return userlottos.lottos - .map { numbers -> numbers.countMatch(winningWinningLotto.winningLotto) } - .map { LottoMatch.of(it) } - .sorted() + val lottoMatchResults = mutableListOf() + + for (lotto in userlottos.lottos) { + val matchNumbers = lotto.countMatch(winningLotto.winningLotto) + val matchBonus = lotto.countMatchBonus(winningLotto.bonusNumber) + lottoMatchResults.add(LottoMatch.of(matchNumbers, matchBonus)) + } + + return lottoMatchResults } } From 5cf19dafdbc641268d56005d774c7afa2c84eded Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Wed, 6 Dec 2023 02:14:33 +0900 Subject: [PATCH 58/92] =?UTF-8?q?refactor=20:=20View=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20object=EB=A1=9C=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20?= =?UTF-8?q?=EB=B3=B4=EB=84=88=EC=8A=A4=EB=B3=BC=20Input=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EC=99=80=20=EC=88=98=EC=9D=B5=EB=A5=A0=20pri?= =?UTF-8?q?nt=20=EB=AC=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/nextstep/edu/step/step2/view/InputView.kt | 9 ++++++++- .../camp/nextstep/edu/step/step2/view/OutputView.kt | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt index c2a9fdb068..ae5d9c8a79 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt @@ -2,8 +2,10 @@ package camp.nextstep.edu.step.step2.view import camp.nextstep.edu.step.step2.domain.amount.BuyAmount import camp.nextstep.edu.step.step2.domain.lotto.Lotto +import camp.nextstep.edu.step.step2.domain.number.BonusNumber +import camp.nextstep.edu.step.step2.domain.number.Number -class InputView { +object InputView { fun getInputValueAndReturnBuyAmount(): BuyAmount { println("구입금액을 입력해 주세요.") @@ -15,4 +17,9 @@ class InputView { return Lotto.ofInputValues(numbers = readLine()!!) } + fun inputBonusNumber(): BonusNumber { + println("보너스 볼을 입력해 주세요.") + return BonusNumber(number = Number(number = readLine()!!.toInt())) + } + } diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt index 600fe136ec..19027e16f5 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt @@ -2,7 +2,7 @@ package camp.nextstep.edu.step.step2.view import camp.nextstep.edu.step.step2.dto.LottoResultDto -class OutputView { +object OutputView { fun displayTicketsNumbers(ticketsAmount: Int, ticketNumbers: List>) { println("${ticketsAmount}개를 구매했습니다.") @@ -18,7 +18,7 @@ class OutputView { lottoResultDto.matchResponse.forEach { matchResponse -> println("${matchResponse.matchCount}개 일치 (${matchResponse.prize}원) - ${matchResponse.userMatchCont}개") } - println("총 수익률은 ${lottoResultDto.lottoProfitRate}입니다.") + println("총 수익률은 %.2f 입니다.".format(lottoResultDto.lottoProfitRate)) } } From 9855cccae9199ac3c24e34a0c5a36c1be0e3b2c9 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Wed, 6 Dec 2023 02:15:45 +0900 Subject: [PATCH 59/92] =?UTF-8?q?refactor=20:=20Main=20=ED=95=A8=EC=88=98?= =?UTF-8?q?=20=EB=82=B4=20=EB=B9=84=EC=A7=80=EB=8B=88=EC=8A=A4=20=ED=9D=90?= =?UTF-8?q?=EB=A6=84=EB=B3=84=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC=20=EC=A7=84=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 티켓 구매 -> 로또 진행 -> 결과 순으로 비지니스가 눈에 보일 수 있도록 private 메서드로 분리 --- .../camp/nextstep/edu/step/step2/main.kt | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt index 3e983c9d03..216e548566 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt @@ -1,34 +1,47 @@ package camp.nextstep.edu.step.step2 +import camp.nextstep.edu.step.step2.domain.amount.BuyAmount +import camp.nextstep.edu.step.step2.domain.lotto.Lottos import camp.nextstep.edu.step.step2.domain.lotto.WinningLotto import camp.nextstep.edu.step.step2.domain.store.LottoStore import camp.nextstep.edu.step.step2.view.InputView import camp.nextstep.edu.step.step2.view.OutputView + fun main() { - val inputView = InputView() - val outputView = OutputView() + val buyAmount = InputView.getInputValueAndReturnBuyAmount() + + val lottos = buyLottoTicketsWithAmount(buyAmount = buyAmount) + + checkLottoTicketsWinningResult(lottos = lottos) +} - val buyAmount = inputView.getInputValueAndReturnBuyAmount() +private fun buyLottoTicketsWithAmount(buyAmount: BuyAmount): Lottos { val tickets = LottoStore.buyLottoTickets(buyAmount = buyAmount) val lottos = LottoStore.createNumbersByLottoTicketAmount(ticketAmount = tickets) val ticketElements = lottos.getLottoElements() - outputView.displayTicketsNumbers( + OutputView.displayTicketsNumbers( ticketsAmount = tickets.lottoTicketAmount, ticketNumbers = ticketElements ) - val lastWeekWinningNumbers = inputView.inputLastWeekWinningNumbers() + return lottos +} + +private fun checkLottoTicketsWinningResult(lottos: Lottos) { + val lastWeekWinningNumbers = InputView.inputLastWeekWinningNumbers() + val bonusNumber = InputView.inputBonusNumber() val lottoResult = LottoStore.checkLottoTicketsWinningResult( userLottos = lottos, winningLotto = WinningLotto( - winningLotto = lastWeekWinningNumbers + winningLotto = lastWeekWinningNumbers, + bonusNumber = bonusNumber ) ) - outputView.displayLottoResultByDto(lottoResultDto = lottoResult.calculateResultAndReturnDto()) + OutputView.displayLottoResultByDto(lottoResultDto = lottoResult.calculateResultAndReturnDto()) } From 15da1fce6bcff7a7c24d9db6762ce7aac72ce24c Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Wed, 6 Dec 2023 02:16:49 +0900 Subject: [PATCH 60/92] =?UTF-8?q?test=20:=20=EB=B3=B4=EB=84=88=EC=8A=A4=20?= =?UTF-8?q?=EC=88=AB=EC=9E=90=20=EC=B6=94=EA=B0=80=EC=97=90=EB=94=B0?= =?UTF-8?q?=EB=A5=B8=20=EA=B0=81=20=EB=8F=84=EB=A9=94=EC=9D=B8=EB=B3=84=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20=EC=9E=AC=20=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=A7=84=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step2/domain/lotto/WinningLottoTest.kt | 13 ++++++-- .../step/step2/domain/number/NumberTest.kt | 1 - .../step2/domain/result/LottoResultTest.kt | 14 ++++---- .../step/step2/domain/store/LottoStoreTest.kt | 32 ++++++++++++++----- 4 files changed, 42 insertions(+), 18 deletions(-) diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt index b79e779de7..2005e71d96 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt @@ -1,5 +1,6 @@ package camp.nextstep.edu.step.step2.domain.lotto +import camp.nextstep.edu.step.step2.domain.number.BonusNumber import camp.nextstep.edu.step.step2.domain.number.Number import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.BehaviorSpec @@ -21,9 +22,12 @@ class WinningLottoTest : BehaviorSpec({ ) ) + val bonusNumber = BonusNumber(number = Number(number = 7)) + When("생성을 요청하면") { val winningLotto = WinningLotto( - winningLotto = winningLottoRequest + winningLotto = winningLottoRequest, + bonusNumber = bonusNumber ) Then("정상적으로 생성된다.") { @@ -35,6 +39,8 @@ class WinningLottoTest : BehaviorSpec({ Number(5), Number(6) ) + + winningLotto.bonusNumber shouldBe BonusNumber(number = Number(number = 7)) } } @@ -45,10 +51,13 @@ class WinningLottoTest : BehaviorSpec({ listOf() ) + val bonusNumber = BonusNumber(number = Number(number = 7)) + When("생성 시") { val exceptionByEmptyLotto = shouldThrow { WinningLotto( - winningLotto = emptyLotto + winningLotto = emptyLotto, + bonusNumber = bonusNumber ) } diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/NumberTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/NumberTest.kt index 90b2e21693..73764d64cf 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/NumberTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/NumberTest.kt @@ -1,6 +1,5 @@ package camp.nextstep.edu.step.step2.domain.number -import camp.nextstep.edu.step.step2.domain.number.Number import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt index cffb11db6c..0f05caa0bf 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt @@ -9,7 +9,7 @@ class LottoResultTest : BehaviorSpec({ Given("로또의 총 금액과, 매치 결과가 주어지면") { val totalPrice = 1000 - val matchResult = listOf(LottoMatch.of(matchCount = 6)) + val matchResult = listOf(LottoMatch.of(matchCount = 6, bonusMatch = 0)) When("로또 결과를 생성하면") { val lottoResult = @@ -18,7 +18,7 @@ class LottoResultTest : BehaviorSpec({ Then("로또 결과가 생성된다") { lottoResult shouldBe LottoResult( lottoTotalPrice = 1000, - lottoResults = listOf(LottoMatch.of(matchCount = 6)) + lottoResults = listOf(LottoMatch.of(matchCount = 6, bonusMatch = 0)) ) } } @@ -26,16 +26,16 @@ class LottoResultTest : BehaviorSpec({ Given("로또 결과 도메인이 주어지고") { val totalPrice = 1000 - val matchResult = listOf(LottoMatch.of(matchCount = 1)) + val matchResult = listOf(LottoMatch.of(matchCount = 1, bonusMatch = 0)) val lottoResult = LottoResult(lottoTotalPrice = totalPrice, lottoResults = matchResult) When("로또 결과 전달을 위한 Dto를 생성하면") { val lottoResultDto = lottoResult.calculateResultAndReturnDto() - Then("로또 결과 Dto가 반환된다") { - lottoResultDto.matchResponse.size shouldBe 5 - lottoResultDto.lottoProfitRate shouldBe 0.0 - } + Then("로또 결과 Dto가 반환된다") { + lottoResultDto.matchResponse.size shouldBe 6 + lottoResultDto.lottoProfitRate shouldBe 0.0 + } } } diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt index f5ca5e8c4d..b8b712f4d7 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt @@ -1,10 +1,11 @@ package camp.nextstep.edu.step.step2.domain.store import camp.nextstep.edu.step.step2.domain.amount.BuyAmount -import camp.nextstep.edu.step.step2.domain.number.Number import camp.nextstep.edu.step.step2.domain.lotto.Lotto import camp.nextstep.edu.step.step2.domain.lotto.Lottos import camp.nextstep.edu.step.step2.domain.lotto.WinningLotto +import camp.nextstep.edu.step.step2.domain.number.BonusNumber +import camp.nextstep.edu.step.step2.domain.number.Number import camp.nextstep.edu.step.step2.domain.result.LottoMatch import camp.nextstep.edu.step.step2.domain.result.LottoResult import io.kotest.core.spec.style.BehaviorSpec @@ -54,20 +55,27 @@ class LottoStoreTest : BehaviorSpec({ ) ) + val bonusNumber = BonusNumber(number = Number(number = 7)) + val winningLotto = WinningLotto( - winningLotto = lastWeekWinningLottoLotto + winningLotto = lastWeekWinningLottoLotto, + bonusNumber = bonusNumber ) When("로또 번호를 검증하면") { val lottoResult = - LottoStore.checkLottoTicketsWinningResult(userLottos = userLottos, winningLotto = winningLotto) + LottoStore.checkLottoTicketsWinningResult( + userLottos = userLottos, + winningLotto = winningLotto + ) Then("로또 결과를 반환한다.") { lottoResult shouldBe LottoResult( lottoTotalPrice = 1000, lottoResults = listOf( LottoMatch.of( - matchCount = 6 + matchCount = 6, + bonusMatch = 0 ) ) ) @@ -79,7 +87,8 @@ class LottoStoreTest : BehaviorSpec({ val lottoTicketAmount = LottoTicketAmount(lottoTicketAmount = 10) When("로또 발급을 시도하면") { - val lottoTickets = LottoStore.createNumbersByLottoTicketAmount(ticketAmount = lottoTicketAmount) + val lottoTickets = + LottoStore.createNumbersByLottoTicketAmount(ticketAmount = lottoTicketAmount) Then("구매한 수량만큼의 로또가 발급된다.") { lottoTickets.lottos.size shouldBe 10 @@ -114,19 +123,26 @@ class LottoStoreTest : BehaviorSpec({ ) ) + val bonusNumber = BonusNumber(number = Number(number = 7)) + val winningLotto = WinningLotto( - winningLotto = lastWeekWinningLottoLotto + winningLotto = lastWeekWinningLottoLotto, + bonusNumber = bonusNumber ) When("당첨 결과를 확인하면") { - val lottoResult = LottoStore.checkLottoTicketsWinningResult(userLottos = userLottos, winningLotto = winningLotto) + val lottoResult = LottoStore.checkLottoTicketsWinningResult( + userLottos = userLottos, + winningLotto = winningLotto + ) Then("당첨 결과를 반환한다.") { lottoResult shouldBe LottoResult( lottoTotalPrice = 1000, lottoResults = listOf( LottoMatch.of( - matchCount = 6 + matchCount = 6, + bonusMatch = 0 ) ) ) From 07ea3e4817f7811273f25cdb3cfb3971925c818b Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Wed, 6 Dec 2023 02:17:04 +0900 Subject: [PATCH 61/92] =?UTF-8?q?test=20:=20=EB=B3=B4=EB=84=88=EC=8A=A4=20?= =?UTF-8?q?=EC=88=AB=EC=9E=90=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step2/domain/number/BonusNumberTest.kt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumberTest.kt diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumberTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumberTest.kt new file mode 100644 index 0000000000..2600de91ce --- /dev/null +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumberTest.kt @@ -0,0 +1,22 @@ +package camp.nextstep.edu.step.step2.domain.number + +import io.kotest.core.annotation.DisplayName +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe + +@DisplayName("보너스 번호는") +class BonusNumberTest : BehaviorSpec({ + + Given("번호가 주어지고") { + val number = 1 + + When("보너스 번호를 생성하면") { + val bonusNumber = BonusNumber(number = Number(number = number)) + + Then("보너스 번호가 생성된다") { + bonusNumber.number shouldBe Number(number = 1) + } + } + } + +}) From 4b72c0ea8908368d95a9831f63846b1018c0ab4a Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Wed, 6 Dec 2023 02:17:37 +0900 Subject: [PATCH 62/92] =?UTF-8?q?docs=20:=20Step3=20=EB=A6=AC=EB=93=9C?= =?UTF-8?q?=EB=AF=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 52a3f84121..fba636cfbf 100644 --- a/README.md +++ b/README.md @@ -39,3 +39,16 @@ - 당첨 내용에 따른 통계 계산이 가능하다. - 이전 당첨번호를 통해 당첨 여부 확인이 가능하다. - 로또의 총 금액은 0보다 커야한다. + + +# Step3 - 로또 2등구현 ( Lotto ) +추가적인 요구사항 +- 지난 주 당첨번호 입력이 완료된 이후, 보너스 볼 입력이 이뤄져야 한다. +- 당첨 통계 시, 5개 일치 + 보너스 볼 일치의 경우 2등으로 처리한다. + +개인적인 수정사항 +- 로또 당첨율 View를 수정한다. ( ex. 0.01 )과 같이 소수점 2자리까지 표현한다. +- Main 함수 내, 비지니스 흐름을 파악할 수 있도록 리펙토링을 재 진행한다. + +추가한 도메인 +- 보너스 숫자 ( BonusNumber ) From cdab130551118e9841c7e20f789fc329af70a31e Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 6 Dec 2023 23:50:34 +0900 Subject: [PATCH 63/92] chore : git revert --- README.md | 13 -------- .../edu/step/step2/domain/lotto/Lotto.kt | 7 ---- .../step2/domain/{number => lotto}/Number.kt | 2 +- .../step/step2/domain/lotto/WinningLotto.kt | 3 -- .../step/step2/domain/number/BonusNumber.kt | 12 ------- .../step/step2/domain/result/LottoMatch.kt | 16 ++++------ .../edu/step/step2/domain/store/LottoStore.kt | 17 ++++------ .../step/step2/generator/NumberGenerator.kt | 2 +- .../camp/nextstep/edu/step/step2/main.kt | 27 ++++------------ .../nextstep/edu/step/step2/view/InputView.kt | 9 +----- .../edu/step/step2/view/OutputView.kt | 4 +-- .../edu/step/step2/domain/lotto/LottoTest.kt | 1 - .../domain/{number => lotto}/NumberTest.kt | 2 +- .../step2/domain/lotto/WinningLottoTest.kt | 14 ++------ .../step2/domain/number/BonusNumberTest.kt | 22 ------------- .../step2/domain/result/LottoResultTest.kt | 14 ++++---- .../step/step2/domain/store/LottoStoreTest.kt | 32 +++++-------------- 17 files changed, 43 insertions(+), 154 deletions(-) rename src/main/kotlin/camp/nextstep/edu/step/step2/domain/{number => lotto}/Number.kt (76%) delete mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumber.kt rename src/test/kotlin/camp/nextstep/edu/step/step2/domain/{number => lotto}/NumberTest.kt (95%) delete mode 100644 src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumberTest.kt diff --git a/README.md b/README.md index fba636cfbf..52a3f84121 100644 --- a/README.md +++ b/README.md @@ -39,16 +39,3 @@ - 당첨 내용에 따른 통계 계산이 가능하다. - 이전 당첨번호를 통해 당첨 여부 확인이 가능하다. - 로또의 총 금액은 0보다 커야한다. - - -# Step3 - 로또 2등구현 ( Lotto ) -추가적인 요구사항 -- 지난 주 당첨번호 입력이 완료된 이후, 보너스 볼 입력이 이뤄져야 한다. -- 당첨 통계 시, 5개 일치 + 보너스 볼 일치의 경우 2등으로 처리한다. - -개인적인 수정사항 -- 로또 당첨율 View를 수정한다. ( ex. 0.01 )과 같이 소수점 2자리까지 표현한다. -- Main 함수 내, 비지니스 흐름을 파악할 수 있도록 리펙토링을 재 진행한다. - -추가한 도메인 -- 보너스 숫자 ( BonusNumber ) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt index 481d7015ad..88839d6171 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt @@ -1,8 +1,5 @@ package camp.nextstep.edu.step.step2.domain.lotto -import camp.nextstep.edu.step.step2.domain.number.BonusNumber -import camp.nextstep.edu.step.step2.domain.number.Number - class Lotto( val numbers: List ) { @@ -11,10 +8,6 @@ class Lotto( return numbers.count { targetLotto.numbers.contains(it) } } - fun countMatchBonus(bonusNumber: BonusNumber): Int { - return numbers.count { it.number == bonusNumber.getNumberElement() } - } - fun getNumberElements(): List { return numbers.map { it.number } } diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/Number.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Number.kt similarity index 76% rename from src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/Number.kt rename to src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Number.kt index ecc149f579..858c08f577 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/Number.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Number.kt @@ -1,4 +1,4 @@ -package camp.nextstep.edu.step.step2.domain.number +package camp.nextstep.edu.step.step2.domain.lotto @JvmInline value class Number( diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt index b5155c1dfe..82cd6cfee7 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt @@ -1,10 +1,7 @@ package camp.nextstep.edu.step.step2.domain.lotto -import camp.nextstep.edu.step.step2.domain.number.BonusNumber - data class WinningLotto( val winningLotto: Lotto, - val bonusNumber: BonusNumber ) { init { diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumber.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumber.kt deleted file mode 100644 index 76c67e53d8..0000000000 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumber.kt +++ /dev/null @@ -1,12 +0,0 @@ -package camp.nextstep.edu.step.step2.domain.number - - -class BonusNumber( - val number: Number -) { - - fun getNumberElement(): Int { - return number.number - } - -} diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoMatch.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoMatch.kt index 73446ecc0c..99644e4d95 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoMatch.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoMatch.kt @@ -2,20 +2,18 @@ package camp.nextstep.edu.step.step2.domain.result enum class LottoMatch( val matchCount: Int, - val bonusMatch: Int, val prize: Int ) { - SIX_MATCH(6, 0, 2_000_000_000), - FIVE_MATCH(5, 0, 1_500_000), - FIVE_MATCH_WITH_BONUS(5, 1, 30_000_000), - FOUR_MATCH(4, 0,50_000), - THREE_MATCH(3, 0,5_000), - NONE(0, 0,0); + SIX_MATCH(6, 2_000_000_000), + FIVE_MATCH(5, 1_500_000), + FOUR_MATCH(4, 50_000), + THREE_MATCH(3, 5_000), + NONE(0, 0); companion object { - fun of(matchCount: Int, bonusMatch: Int): LottoMatch { - return values().find { it.matchCount == matchCount && it.bonusMatch == bonusMatch } ?: NONE + fun of(matchCount: Int): LottoMatch { + return values().find { it.matchCount == matchCount } ?: NONE } } } diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt index 729b10bf9b..b5687dab56 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt @@ -55,7 +55,7 @@ object LottoStore { val matchResult = lottoWinningResults( userlottos = userLottos, - winningLotto = winningLotto + winningWinningLotto = winningLotto ) return LottoResult(totalPrice, matchResult) @@ -73,17 +73,12 @@ object LottoStore { */ private fun lottoWinningResults( userlottos: Lottos, - winningLotto: WinningLotto + winningWinningLotto: WinningLotto ): List { - val lottoMatchResults = mutableListOf() - - for (lotto in userlottos.lottos) { - val matchNumbers = lotto.countMatch(winningLotto.winningLotto) - val matchBonus = lotto.countMatchBonus(winningLotto.bonusNumber) - lottoMatchResults.add(LottoMatch.of(matchNumbers, matchBonus)) - } - - return lottoMatchResults + return userlottos.lottos + .map { numbers -> numbers.countMatch(winningWinningLotto.winningLotto) } + .map { LottoMatch.of(it) } + .sorted() } } diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt index c89716b3f9..9bb5daaf73 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt @@ -1,6 +1,6 @@ package camp.nextstep.edu.step.step2.generator -import camp.nextstep.edu.step.step2.domain.number.Number +import camp.nextstep.edu.step.step2.domain.lotto.Number enum class NumberGenerator( val generate: (Int, Int) -> List diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt index 216e548566..3e983c9d03 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt @@ -1,47 +1,34 @@ package camp.nextstep.edu.step.step2 -import camp.nextstep.edu.step.step2.domain.amount.BuyAmount -import camp.nextstep.edu.step.step2.domain.lotto.Lottos import camp.nextstep.edu.step.step2.domain.lotto.WinningLotto import camp.nextstep.edu.step.step2.domain.store.LottoStore import camp.nextstep.edu.step.step2.view.InputView import camp.nextstep.edu.step.step2.view.OutputView - fun main() { - val buyAmount = InputView.getInputValueAndReturnBuyAmount() - - val lottos = buyLottoTicketsWithAmount(buyAmount = buyAmount) - - checkLottoTicketsWinningResult(lottos = lottos) -} + val inputView = InputView() + val outputView = OutputView() -private fun buyLottoTicketsWithAmount(buyAmount: BuyAmount): Lottos { + val buyAmount = inputView.getInputValueAndReturnBuyAmount() val tickets = LottoStore.buyLottoTickets(buyAmount = buyAmount) val lottos = LottoStore.createNumbersByLottoTicketAmount(ticketAmount = tickets) val ticketElements = lottos.getLottoElements() - OutputView.displayTicketsNumbers( + outputView.displayTicketsNumbers( ticketsAmount = tickets.lottoTicketAmount, ticketNumbers = ticketElements ) - return lottos -} - -private fun checkLottoTicketsWinningResult(lottos: Lottos) { - val lastWeekWinningNumbers = InputView.inputLastWeekWinningNumbers() - val bonusNumber = InputView.inputBonusNumber() + val lastWeekWinningNumbers = inputView.inputLastWeekWinningNumbers() val lottoResult = LottoStore.checkLottoTicketsWinningResult( userLottos = lottos, winningLotto = WinningLotto( - winningLotto = lastWeekWinningNumbers, - bonusNumber = bonusNumber + winningLotto = lastWeekWinningNumbers ) ) - OutputView.displayLottoResultByDto(lottoResultDto = lottoResult.calculateResultAndReturnDto()) + outputView.displayLottoResultByDto(lottoResultDto = lottoResult.calculateResultAndReturnDto()) } diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt index ae5d9c8a79..c2a9fdb068 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt @@ -2,10 +2,8 @@ package camp.nextstep.edu.step.step2.view import camp.nextstep.edu.step.step2.domain.amount.BuyAmount import camp.nextstep.edu.step.step2.domain.lotto.Lotto -import camp.nextstep.edu.step.step2.domain.number.BonusNumber -import camp.nextstep.edu.step.step2.domain.number.Number -object InputView { +class InputView { fun getInputValueAndReturnBuyAmount(): BuyAmount { println("구입금액을 입력해 주세요.") @@ -17,9 +15,4 @@ object InputView { return Lotto.ofInputValues(numbers = readLine()!!) } - fun inputBonusNumber(): BonusNumber { - println("보너스 볼을 입력해 주세요.") - return BonusNumber(number = Number(number = readLine()!!.toInt())) - } - } diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt index 19027e16f5..600fe136ec 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt @@ -2,7 +2,7 @@ package camp.nextstep.edu.step.step2.view import camp.nextstep.edu.step.step2.dto.LottoResultDto -object OutputView { +class OutputView { fun displayTicketsNumbers(ticketsAmount: Int, ticketNumbers: List>) { println("${ticketsAmount}개를 구매했습니다.") @@ -18,7 +18,7 @@ object OutputView { lottoResultDto.matchResponse.forEach { matchResponse -> println("${matchResponse.matchCount}개 일치 (${matchResponse.prize}원) - ${matchResponse.userMatchCont}개") } - println("총 수익률은 %.2f 입니다.".format(lottoResultDto.lottoProfitRate)) + println("총 수익률은 ${lottoResultDto.lottoProfitRate}입니다.") } } diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt index 9995796252..00ada13892 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt @@ -1,6 +1,5 @@ package camp.nextstep.edu.step.step2.domain.lotto -import camp.nextstep.edu.step.step2.domain.number.Number import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe import org.junit.jupiter.api.DisplayName diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/NumberTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumberTest.kt similarity index 95% rename from src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/NumberTest.kt rename to src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumberTest.kt index 73764d64cf..5689e20629 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/NumberTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumberTest.kt @@ -1,4 +1,4 @@ -package camp.nextstep.edu.step.step2.domain.number +package camp.nextstep.edu.step.step2.domain.lotto import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.BehaviorSpec diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt index 2005e71d96..a53a21180a 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt @@ -1,7 +1,5 @@ package camp.nextstep.edu.step.step2.domain.lotto -import camp.nextstep.edu.step.step2.domain.number.BonusNumber -import camp.nextstep.edu.step.step2.domain.number.Number import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe @@ -22,12 +20,9 @@ class WinningLottoTest : BehaviorSpec({ ) ) - val bonusNumber = BonusNumber(number = Number(number = 7)) - When("생성을 요청하면") { val winningLotto = WinningLotto( - winningLotto = winningLottoRequest, - bonusNumber = bonusNumber + winningLotto = winningLottoRequest ) Then("정상적으로 생성된다.") { @@ -39,8 +34,6 @@ class WinningLottoTest : BehaviorSpec({ Number(5), Number(6) ) - - winningLotto.bonusNumber shouldBe BonusNumber(number = Number(number = 7)) } } @@ -51,13 +44,10 @@ class WinningLottoTest : BehaviorSpec({ listOf() ) - val bonusNumber = BonusNumber(number = Number(number = 7)) - When("생성 시") { val exceptionByEmptyLotto = shouldThrow { WinningLotto( - winningLotto = emptyLotto, - bonusNumber = bonusNumber + winningLotto = emptyLotto ) } diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumberTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumberTest.kt deleted file mode 100644 index 2600de91ce..0000000000 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumberTest.kt +++ /dev/null @@ -1,22 +0,0 @@ -package camp.nextstep.edu.step.step2.domain.number - -import io.kotest.core.annotation.DisplayName -import io.kotest.core.spec.style.BehaviorSpec -import io.kotest.matchers.shouldBe - -@DisplayName("보너스 번호는") -class BonusNumberTest : BehaviorSpec({ - - Given("번호가 주어지고") { - val number = 1 - - When("보너스 번호를 생성하면") { - val bonusNumber = BonusNumber(number = Number(number = number)) - - Then("보너스 번호가 생성된다") { - bonusNumber.number shouldBe Number(number = 1) - } - } - } - -}) diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt index 0f05caa0bf..cffb11db6c 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt @@ -9,7 +9,7 @@ class LottoResultTest : BehaviorSpec({ Given("로또의 총 금액과, 매치 결과가 주어지면") { val totalPrice = 1000 - val matchResult = listOf(LottoMatch.of(matchCount = 6, bonusMatch = 0)) + val matchResult = listOf(LottoMatch.of(matchCount = 6)) When("로또 결과를 생성하면") { val lottoResult = @@ -18,7 +18,7 @@ class LottoResultTest : BehaviorSpec({ Then("로또 결과가 생성된다") { lottoResult shouldBe LottoResult( lottoTotalPrice = 1000, - lottoResults = listOf(LottoMatch.of(matchCount = 6, bonusMatch = 0)) + lottoResults = listOf(LottoMatch.of(matchCount = 6)) ) } } @@ -26,16 +26,16 @@ class LottoResultTest : BehaviorSpec({ Given("로또 결과 도메인이 주어지고") { val totalPrice = 1000 - val matchResult = listOf(LottoMatch.of(matchCount = 1, bonusMatch = 0)) + val matchResult = listOf(LottoMatch.of(matchCount = 1)) val lottoResult = LottoResult(lottoTotalPrice = totalPrice, lottoResults = matchResult) When("로또 결과 전달을 위한 Dto를 생성하면") { val lottoResultDto = lottoResult.calculateResultAndReturnDto() - Then("로또 결과 Dto가 반환된다") { - lottoResultDto.matchResponse.size shouldBe 6 - lottoResultDto.lottoProfitRate shouldBe 0.0 - } + Then("로또 결과 Dto가 반환된다") { + lottoResultDto.matchResponse.size shouldBe 5 + lottoResultDto.lottoProfitRate shouldBe 0.0 + } } } diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt index b8b712f4d7..c82d3b3c3d 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt @@ -1,11 +1,10 @@ package camp.nextstep.edu.step.step2.domain.store import camp.nextstep.edu.step.step2.domain.amount.BuyAmount +import camp.nextstep.edu.step.step2.domain.lotto.Number import camp.nextstep.edu.step.step2.domain.lotto.Lotto import camp.nextstep.edu.step.step2.domain.lotto.Lottos import camp.nextstep.edu.step.step2.domain.lotto.WinningLotto -import camp.nextstep.edu.step.step2.domain.number.BonusNumber -import camp.nextstep.edu.step.step2.domain.number.Number import camp.nextstep.edu.step.step2.domain.result.LottoMatch import camp.nextstep.edu.step.step2.domain.result.LottoResult import io.kotest.core.spec.style.BehaviorSpec @@ -55,27 +54,20 @@ class LottoStoreTest : BehaviorSpec({ ) ) - val bonusNumber = BonusNumber(number = Number(number = 7)) - val winningLotto = WinningLotto( - winningLotto = lastWeekWinningLottoLotto, - bonusNumber = bonusNumber + winningLotto = lastWeekWinningLottoLotto ) When("로또 번호를 검증하면") { val lottoResult = - LottoStore.checkLottoTicketsWinningResult( - userLottos = userLottos, - winningLotto = winningLotto - ) + LottoStore.checkLottoTicketsWinningResult(userLottos = userLottos, winningLotto = winningLotto) Then("로또 결과를 반환한다.") { lottoResult shouldBe LottoResult( lottoTotalPrice = 1000, lottoResults = listOf( LottoMatch.of( - matchCount = 6, - bonusMatch = 0 + matchCount = 6 ) ) ) @@ -87,8 +79,7 @@ class LottoStoreTest : BehaviorSpec({ val lottoTicketAmount = LottoTicketAmount(lottoTicketAmount = 10) When("로또 발급을 시도하면") { - val lottoTickets = - LottoStore.createNumbersByLottoTicketAmount(ticketAmount = lottoTicketAmount) + val lottoTickets = LottoStore.createNumbersByLottoTicketAmount(ticketAmount = lottoTicketAmount) Then("구매한 수량만큼의 로또가 발급된다.") { lottoTickets.lottos.size shouldBe 10 @@ -123,26 +114,19 @@ class LottoStoreTest : BehaviorSpec({ ) ) - val bonusNumber = BonusNumber(number = Number(number = 7)) - val winningLotto = WinningLotto( - winningLotto = lastWeekWinningLottoLotto, - bonusNumber = bonusNumber + winningLotto = lastWeekWinningLottoLotto ) When("당첨 결과를 확인하면") { - val lottoResult = LottoStore.checkLottoTicketsWinningResult( - userLottos = userLottos, - winningLotto = winningLotto - ) + val lottoResult = LottoStore.checkLottoTicketsWinningResult(userLottos = userLottos, winningLotto = winningLotto) Then("당첨 결과를 반환한다.") { lottoResult shouldBe LottoResult( lottoTotalPrice = 1000, lottoResults = listOf( LottoMatch.of( - matchCount = 6, - bonusMatch = 0 + matchCount = 6 ) ) ) From 409251d9b6ee6b6938081b698e417c7b759d743b Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 6 Dec 2023 23:53:15 +0900 Subject: [PATCH 64/92] =?UTF-8?q?chore=20:=20Number=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=9D=B4=EB=8F=99=20?= =?UTF-8?q?(=20Lotto=20->=20Number=20)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nextstep/edu/step/step2/domain/{lotto => number}/Number.kt | 2 +- .../camp/nextstep/edu/step/step2/generator/NumberGenerator.kt | 2 +- .../camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt | 1 + .../edu/step/step2/domain/{lotto => number}/NumberTest.kt | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) rename src/main/kotlin/camp/nextstep/edu/step/step2/domain/{lotto => number}/Number.kt (76%) rename src/test/kotlin/camp/nextstep/edu/step/step2/domain/{lotto => number}/NumberTest.kt (95%) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Number.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/Number.kt similarity index 76% rename from src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Number.kt rename to src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/Number.kt index 858c08f577..ecc149f579 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Number.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/Number.kt @@ -1,4 +1,4 @@ -package camp.nextstep.edu.step.step2.domain.lotto +package camp.nextstep.edu.step.step2.domain.number @JvmInline value class Number( diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt index 9bb5daaf73..c89716b3f9 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt @@ -1,6 +1,6 @@ package camp.nextstep.edu.step.step2.generator -import camp.nextstep.edu.step.step2.domain.lotto.Number +import camp.nextstep.edu.step.step2.domain.number.Number enum class NumberGenerator( val generate: (Int, Int) -> List diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt index 00ada13892..9995796252 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottoTest.kt @@ -1,5 +1,6 @@ package camp.nextstep.edu.step.step2.domain.lotto +import camp.nextstep.edu.step.step2.domain.number.Number import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe import org.junit.jupiter.api.DisplayName diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumberTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/NumberTest.kt similarity index 95% rename from src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumberTest.kt rename to src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/NumberTest.kt index 5689e20629..73764d64cf 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/NumberTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/NumberTest.kt @@ -1,4 +1,4 @@ -package camp.nextstep.edu.step.step2.domain.lotto +package camp.nextstep.edu.step.step2.domain.number import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.BehaviorSpec From a3aed21b68d47c2618bd24241fa67ff4f194ac74 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 6 Dec 2023 23:53:35 +0900 Subject: [PATCH 65/92] =?UTF-8?q?feat=20:=20=EB=B3=B4=EB=84=88=EC=8A=A4=20?= =?UTF-8?q?=EC=88=AB=EC=9E=90=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step2/domain/number/BonusNumber.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumber.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumber.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumber.kt new file mode 100644 index 0000000000..76c67e53d8 --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumber.kt @@ -0,0 +1,12 @@ +package camp.nextstep.edu.step.step2.domain.number + + +class BonusNumber( + val number: Number +) { + + fun getNumberElement(): Int { + return number.number + } + +} From 3f301a97a1b7477577cbc872726231593aca96be Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 6 Dec 2023 23:53:58 +0900 Subject: [PATCH 66/92] =?UTF-8?q?refactor=20:=20=EB=B3=B4=EB=84=88?= =?UTF-8?q?=EC=8A=A4=20=EC=88=AB=EC=9E=90=20=EA=B2=80=EC=A6=9D=EC=9D=84=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20Match=20Enum=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step2/domain/result/LottoMatch.kt | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoMatch.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoMatch.kt index 99644e4d95..73446ecc0c 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoMatch.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoMatch.kt @@ -2,18 +2,20 @@ package camp.nextstep.edu.step.step2.domain.result enum class LottoMatch( val matchCount: Int, + val bonusMatch: Int, val prize: Int ) { - SIX_MATCH(6, 2_000_000_000), - FIVE_MATCH(5, 1_500_000), - FOUR_MATCH(4, 50_000), - THREE_MATCH(3, 5_000), - NONE(0, 0); + SIX_MATCH(6, 0, 2_000_000_000), + FIVE_MATCH(5, 0, 1_500_000), + FIVE_MATCH_WITH_BONUS(5, 1, 30_000_000), + FOUR_MATCH(4, 0,50_000), + THREE_MATCH(3, 0,5_000), + NONE(0, 0,0); companion object { - fun of(matchCount: Int): LottoMatch { - return values().find { it.matchCount == matchCount } ?: NONE + fun of(matchCount: Int, bonusMatch: Int): LottoMatch { + return values().find { it.matchCount == matchCount && it.bonusMatch == bonusMatch } ?: NONE } } } From 09180db90154d939bb98e9cd1dbbfc675fd7a831 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 6 Dec 2023 23:54:22 +0900 Subject: [PATCH 67/92] =?UTF-8?q?refactor=20:=20Lotto=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=82=B4,=20=EB=B3=B4=EB=84=88=EC=8A=A4=20?= =?UTF-8?q?=EC=88=AB=EC=9E=90=20=EA=B2=80=EC=A6=9D=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20Count=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt index 88839d6171..481d7015ad 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt @@ -1,5 +1,8 @@ package camp.nextstep.edu.step.step2.domain.lotto +import camp.nextstep.edu.step.step2.domain.number.BonusNumber +import camp.nextstep.edu.step.step2.domain.number.Number + class Lotto( val numbers: List ) { @@ -8,6 +11,10 @@ class Lotto( return numbers.count { targetLotto.numbers.contains(it) } } + fun countMatchBonus(bonusNumber: BonusNumber): Int { + return numbers.count { it.number == bonusNumber.getNumberElement() } + } + fun getNumberElements(): List { return numbers.map { it.number } } From 87f2a3de1d3221075407598419f18d5d76390fa4 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 6 Dec 2023 23:54:42 +0900 Subject: [PATCH 68/92] =?UTF-8?q?refactor=20:=20=EA=B2=B0=EA=B3=BC=20?= =?UTF-8?q?=EB=A1=9C=EB=98=90=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=82=B4=20?= =?UTF-8?q?=EB=B3=B4=EB=84=88=EC=8A=A4=20=EC=88=AB=EC=9E=90=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt index 82cd6cfee7..b5155c1dfe 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt @@ -1,7 +1,10 @@ package camp.nextstep.edu.step.step2.domain.lotto +import camp.nextstep.edu.step.step2.domain.number.BonusNumber + data class WinningLotto( val winningLotto: Lotto, + val bonusNumber: BonusNumber ) { init { From 998da3aed525292f20bc1abda5d43c1566fa48bb Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 6 Dec 2023 23:55:15 +0900 Subject: [PATCH 69/92] =?UTF-8?q?refactor=20:=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EC=83=81=EC=A0=90=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=82=B4=20?= =?UTF-8?q?=EC=96=B4=EC=83=89=ED=95=9C=20=EB=B3=80=EC=88=98=EB=AA=85=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EA=B2=B0=EA=B3=BC=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit winningWinningLotto -> winningLotto로 수정 --- .../edu/step/step2/domain/store/LottoStore.kt | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt index b5687dab56..729b10bf9b 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt @@ -55,7 +55,7 @@ object LottoStore { val matchResult = lottoWinningResults( userlottos = userLottos, - winningWinningLotto = winningLotto + winningLotto = winningLotto ) return LottoResult(totalPrice, matchResult) @@ -73,12 +73,17 @@ object LottoStore { */ private fun lottoWinningResults( userlottos: Lottos, - winningWinningLotto: WinningLotto + winningLotto: WinningLotto ): List { - return userlottos.lottos - .map { numbers -> numbers.countMatch(winningWinningLotto.winningLotto) } - .map { LottoMatch.of(it) } - .sorted() + val lottoMatchResults = mutableListOf() + + for (lotto in userlottos.lottos) { + val matchNumbers = lotto.countMatch(winningLotto.winningLotto) + val matchBonus = lotto.countMatchBonus(winningLotto.bonusNumber) + lottoMatchResults.add(LottoMatch.of(matchNumbers, matchBonus)) + } + + return lottoMatchResults } } From ea8837ae95f58948ff2e02a678e09a024ce00778 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 6 Dec 2023 23:55:48 +0900 Subject: [PATCH 70/92] =?UTF-8?q?refactor=20:=20View=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20object=EB=A1=9C=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20?= =?UTF-8?q?=EB=B3=B4=EB=84=88=EC=8A=A4=20=EB=B3=BC=20input=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EC=99=80=20=EC=88=98=EC=9D=B5=EB=A5=A0=20pri?= =?UTF-8?q?nt=EB=AC=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/nextstep/edu/step/step2/view/InputView.kt | 9 ++++++++- .../camp/nextstep/edu/step/step2/view/OutputView.kt | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt index c2a9fdb068..ae5d9c8a79 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt @@ -2,8 +2,10 @@ package camp.nextstep.edu.step.step2.view import camp.nextstep.edu.step.step2.domain.amount.BuyAmount import camp.nextstep.edu.step.step2.domain.lotto.Lotto +import camp.nextstep.edu.step.step2.domain.number.BonusNumber +import camp.nextstep.edu.step.step2.domain.number.Number -class InputView { +object InputView { fun getInputValueAndReturnBuyAmount(): BuyAmount { println("구입금액을 입력해 주세요.") @@ -15,4 +17,9 @@ class InputView { return Lotto.ofInputValues(numbers = readLine()!!) } + fun inputBonusNumber(): BonusNumber { + println("보너스 볼을 입력해 주세요.") + return BonusNumber(number = Number(number = readLine()!!.toInt())) + } + } diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt index 600fe136ec..19027e16f5 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt @@ -2,7 +2,7 @@ package camp.nextstep.edu.step.step2.view import camp.nextstep.edu.step.step2.dto.LottoResultDto -class OutputView { +object OutputView { fun displayTicketsNumbers(ticketsAmount: Int, ticketNumbers: List>) { println("${ticketsAmount}개를 구매했습니다.") @@ -18,7 +18,7 @@ class OutputView { lottoResultDto.matchResponse.forEach { matchResponse -> println("${matchResponse.matchCount}개 일치 (${matchResponse.prize}원) - ${matchResponse.userMatchCont}개") } - println("총 수익률은 ${lottoResultDto.lottoProfitRate}입니다.") + println("총 수익률은 %.2f 입니다.".format(lottoResultDto.lottoProfitRate)) } } From d047c1cd3158c3ab727cd43c9731de8697215fc7 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 6 Dec 2023 23:56:19 +0900 Subject: [PATCH 71/92] =?UTF-8?q?refactor=20:=20Main=20=ED=95=A8=EC=88=98?= =?UTF-8?q?=20=EB=82=B4=20=EB=B9=84=EC=A7=80=EB=8B=88=EC=8A=A4=20=ED=9D=90?= =?UTF-8?q?=EB=A6=84=EB=B3=84=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC=20=EC=A7=84=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 티켓 구매 -> 로또 진행 -> 결과 순으로 비지니스가 눈에 보일 수 있도록 private 메서드로 분리 --- .../camp/nextstep/edu/step/step2/main.kt | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt index 3e983c9d03..216e548566 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt @@ -1,34 +1,47 @@ package camp.nextstep.edu.step.step2 +import camp.nextstep.edu.step.step2.domain.amount.BuyAmount +import camp.nextstep.edu.step.step2.domain.lotto.Lottos import camp.nextstep.edu.step.step2.domain.lotto.WinningLotto import camp.nextstep.edu.step.step2.domain.store.LottoStore import camp.nextstep.edu.step.step2.view.InputView import camp.nextstep.edu.step.step2.view.OutputView + fun main() { - val inputView = InputView() - val outputView = OutputView() + val buyAmount = InputView.getInputValueAndReturnBuyAmount() + + val lottos = buyLottoTicketsWithAmount(buyAmount = buyAmount) + + checkLottoTicketsWinningResult(lottos = lottos) +} - val buyAmount = inputView.getInputValueAndReturnBuyAmount() +private fun buyLottoTicketsWithAmount(buyAmount: BuyAmount): Lottos { val tickets = LottoStore.buyLottoTickets(buyAmount = buyAmount) val lottos = LottoStore.createNumbersByLottoTicketAmount(ticketAmount = tickets) val ticketElements = lottos.getLottoElements() - outputView.displayTicketsNumbers( + OutputView.displayTicketsNumbers( ticketsAmount = tickets.lottoTicketAmount, ticketNumbers = ticketElements ) - val lastWeekWinningNumbers = inputView.inputLastWeekWinningNumbers() + return lottos +} + +private fun checkLottoTicketsWinningResult(lottos: Lottos) { + val lastWeekWinningNumbers = InputView.inputLastWeekWinningNumbers() + val bonusNumber = InputView.inputBonusNumber() val lottoResult = LottoStore.checkLottoTicketsWinningResult( userLottos = lottos, winningLotto = WinningLotto( - winningLotto = lastWeekWinningNumbers + winningLotto = lastWeekWinningNumbers, + bonusNumber = bonusNumber ) ) - outputView.displayLottoResultByDto(lottoResultDto = lottoResult.calculateResultAndReturnDto()) + OutputView.displayLottoResultByDto(lottoResultDto = lottoResult.calculateResultAndReturnDto()) } From 6560e92dacbf953e4c02c7297f725ada0d5ca89b Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 6 Dec 2023 23:56:46 +0900 Subject: [PATCH 72/92] =?UTF-8?q?test=20:=20=EB=B3=B4=EB=84=88=EC=8A=A4=20?= =?UTF-8?q?=EC=88=AB=EC=9E=90=20=EC=B6=94=EA=B0=80=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=A5=B8=20=EA=B0=81=20=EB=8F=84=EB=A9=94=EC=9D=B8=EB=B3=84=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20=EC=9E=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=A7=84=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step2/domain/lotto/WinningLottoTest.kt | 14 ++++++-- .../step2/domain/result/LottoResultTest.kt | 14 ++++---- .../step/step2/domain/store/LottoStoreTest.kt | 32 ++++++++++++++----- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt index a53a21180a..2005e71d96 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt @@ -1,5 +1,7 @@ package camp.nextstep.edu.step.step2.domain.lotto +import camp.nextstep.edu.step.step2.domain.number.BonusNumber +import camp.nextstep.edu.step.step2.domain.number.Number import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe @@ -20,9 +22,12 @@ class WinningLottoTest : BehaviorSpec({ ) ) + val bonusNumber = BonusNumber(number = Number(number = 7)) + When("생성을 요청하면") { val winningLotto = WinningLotto( - winningLotto = winningLottoRequest + winningLotto = winningLottoRequest, + bonusNumber = bonusNumber ) Then("정상적으로 생성된다.") { @@ -34,6 +39,8 @@ class WinningLottoTest : BehaviorSpec({ Number(5), Number(6) ) + + winningLotto.bonusNumber shouldBe BonusNumber(number = Number(number = 7)) } } @@ -44,10 +51,13 @@ class WinningLottoTest : BehaviorSpec({ listOf() ) + val bonusNumber = BonusNumber(number = Number(number = 7)) + When("생성 시") { val exceptionByEmptyLotto = shouldThrow { WinningLotto( - winningLotto = emptyLotto + winningLotto = emptyLotto, + bonusNumber = bonusNumber ) } diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt index cffb11db6c..0f05caa0bf 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoResultTest.kt @@ -9,7 +9,7 @@ class LottoResultTest : BehaviorSpec({ Given("로또의 총 금액과, 매치 결과가 주어지면") { val totalPrice = 1000 - val matchResult = listOf(LottoMatch.of(matchCount = 6)) + val matchResult = listOf(LottoMatch.of(matchCount = 6, bonusMatch = 0)) When("로또 결과를 생성하면") { val lottoResult = @@ -18,7 +18,7 @@ class LottoResultTest : BehaviorSpec({ Then("로또 결과가 생성된다") { lottoResult shouldBe LottoResult( lottoTotalPrice = 1000, - lottoResults = listOf(LottoMatch.of(matchCount = 6)) + lottoResults = listOf(LottoMatch.of(matchCount = 6, bonusMatch = 0)) ) } } @@ -26,16 +26,16 @@ class LottoResultTest : BehaviorSpec({ Given("로또 결과 도메인이 주어지고") { val totalPrice = 1000 - val matchResult = listOf(LottoMatch.of(matchCount = 1)) + val matchResult = listOf(LottoMatch.of(matchCount = 1, bonusMatch = 0)) val lottoResult = LottoResult(lottoTotalPrice = totalPrice, lottoResults = matchResult) When("로또 결과 전달을 위한 Dto를 생성하면") { val lottoResultDto = lottoResult.calculateResultAndReturnDto() - Then("로또 결과 Dto가 반환된다") { - lottoResultDto.matchResponse.size shouldBe 5 - lottoResultDto.lottoProfitRate shouldBe 0.0 - } + Then("로또 결과 Dto가 반환된다") { + lottoResultDto.matchResponse.size shouldBe 6 + lottoResultDto.lottoProfitRate shouldBe 0.0 + } } } diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt index c82d3b3c3d..b8b712f4d7 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt @@ -1,10 +1,11 @@ package camp.nextstep.edu.step.step2.domain.store import camp.nextstep.edu.step.step2.domain.amount.BuyAmount -import camp.nextstep.edu.step.step2.domain.lotto.Number import camp.nextstep.edu.step.step2.domain.lotto.Lotto import camp.nextstep.edu.step.step2.domain.lotto.Lottos import camp.nextstep.edu.step.step2.domain.lotto.WinningLotto +import camp.nextstep.edu.step.step2.domain.number.BonusNumber +import camp.nextstep.edu.step.step2.domain.number.Number import camp.nextstep.edu.step.step2.domain.result.LottoMatch import camp.nextstep.edu.step.step2.domain.result.LottoResult import io.kotest.core.spec.style.BehaviorSpec @@ -54,20 +55,27 @@ class LottoStoreTest : BehaviorSpec({ ) ) + val bonusNumber = BonusNumber(number = Number(number = 7)) + val winningLotto = WinningLotto( - winningLotto = lastWeekWinningLottoLotto + winningLotto = lastWeekWinningLottoLotto, + bonusNumber = bonusNumber ) When("로또 번호를 검증하면") { val lottoResult = - LottoStore.checkLottoTicketsWinningResult(userLottos = userLottos, winningLotto = winningLotto) + LottoStore.checkLottoTicketsWinningResult( + userLottos = userLottos, + winningLotto = winningLotto + ) Then("로또 결과를 반환한다.") { lottoResult shouldBe LottoResult( lottoTotalPrice = 1000, lottoResults = listOf( LottoMatch.of( - matchCount = 6 + matchCount = 6, + bonusMatch = 0 ) ) ) @@ -79,7 +87,8 @@ class LottoStoreTest : BehaviorSpec({ val lottoTicketAmount = LottoTicketAmount(lottoTicketAmount = 10) When("로또 발급을 시도하면") { - val lottoTickets = LottoStore.createNumbersByLottoTicketAmount(ticketAmount = lottoTicketAmount) + val lottoTickets = + LottoStore.createNumbersByLottoTicketAmount(ticketAmount = lottoTicketAmount) Then("구매한 수량만큼의 로또가 발급된다.") { lottoTickets.lottos.size shouldBe 10 @@ -114,19 +123,26 @@ class LottoStoreTest : BehaviorSpec({ ) ) + val bonusNumber = BonusNumber(number = Number(number = 7)) + val winningLotto = WinningLotto( - winningLotto = lastWeekWinningLottoLotto + winningLotto = lastWeekWinningLottoLotto, + bonusNumber = bonusNumber ) When("당첨 결과를 확인하면") { - val lottoResult = LottoStore.checkLottoTicketsWinningResult(userLottos = userLottos, winningLotto = winningLotto) + val lottoResult = LottoStore.checkLottoTicketsWinningResult( + userLottos = userLottos, + winningLotto = winningLotto + ) Then("당첨 결과를 반환한다.") { lottoResult shouldBe LottoResult( lottoTotalPrice = 1000, lottoResults = listOf( LottoMatch.of( - matchCount = 6 + matchCount = 6, + bonusMatch = 0 ) ) ) From 8bd330f94ccb4e68c94e361c61b8e754bb947026 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 6 Dec 2023 23:56:56 +0900 Subject: [PATCH 73/92] =?UTF-8?q?test=20:=20=EB=B3=B4=EB=84=88=EC=8A=A4=20?= =?UTF-8?q?=EC=88=AB=EC=9E=90=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step2/domain/number/BonusNumberTest.kt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumberTest.kt diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumberTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumberTest.kt new file mode 100644 index 0000000000..2600de91ce --- /dev/null +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumberTest.kt @@ -0,0 +1,22 @@ +package camp.nextstep.edu.step.step2.domain.number + +import io.kotest.core.annotation.DisplayName +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe + +@DisplayName("보너스 번호는") +class BonusNumberTest : BehaviorSpec({ + + Given("번호가 주어지고") { + val number = 1 + + When("보너스 번호를 생성하면") { + val bonusNumber = BonusNumber(number = Number(number = number)) + + Then("보너스 번호가 생성된다") { + bonusNumber.number shouldBe Number(number = 1) + } + } + } + +}) From 8a46177a9793d277950a27951bda60cb522ac881 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 6 Dec 2023 23:57:04 +0900 Subject: [PATCH 74/92] =?UTF-8?q?docs=20:=20Step3=20=EB=A6=AC=EB=93=9C?= =?UTF-8?q?=EB=AF=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 52a3f84121..fba636cfbf 100644 --- a/README.md +++ b/README.md @@ -39,3 +39,16 @@ - 당첨 내용에 따른 통계 계산이 가능하다. - 이전 당첨번호를 통해 당첨 여부 확인이 가능하다. - 로또의 총 금액은 0보다 커야한다. + + +# Step3 - 로또 2등구현 ( Lotto ) +추가적인 요구사항 +- 지난 주 당첨번호 입력이 완료된 이후, 보너스 볼 입력이 이뤄져야 한다. +- 당첨 통계 시, 5개 일치 + 보너스 볼 일치의 경우 2등으로 처리한다. + +개인적인 수정사항 +- 로또 당첨율 View를 수정한다. ( ex. 0.01 )과 같이 소수점 2자리까지 표현한다. +- Main 함수 내, 비지니스 흐름을 파악할 수 있도록 리펙토링을 재 진행한다. + +추가한 도메인 +- 보너스 숫자 ( BonusNumber ) From c82ecd986cf759e00c9bb1552f4ac79332f9cfe8 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Sun, 10 Dec 2023 22:09:24 +0900 Subject: [PATCH 75/92] =?UTF-8?q?refactor=20:=20=EB=B3=B4=EB=84=88?= =?UTF-8?q?=EC=8A=A4=20=EC=88=AB=EC=9E=90=20=EB=8F=84=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step/step2/domain/number/BonusNumber.kt | 12 ---------- .../step2/domain/number/BonusNumberTest.kt | 22 ------------------- 2 files changed, 34 deletions(-) delete mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumber.kt delete mode 100644 src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumberTest.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumber.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumber.kt deleted file mode 100644 index 76c67e53d8..0000000000 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumber.kt +++ /dev/null @@ -1,12 +0,0 @@ -package camp.nextstep.edu.step.step2.domain.number - - -class BonusNumber( - val number: Number -) { - - fun getNumberElement(): Int { - return number.number - } - -} diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumberTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumberTest.kt deleted file mode 100644 index 2600de91ce..0000000000 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/number/BonusNumberTest.kt +++ /dev/null @@ -1,22 +0,0 @@ -package camp.nextstep.edu.step.step2.domain.number - -import io.kotest.core.annotation.DisplayName -import io.kotest.core.spec.style.BehaviorSpec -import io.kotest.matchers.shouldBe - -@DisplayName("보너스 번호는") -class BonusNumberTest : BehaviorSpec({ - - Given("번호가 주어지고") { - val number = 1 - - When("보너스 번호를 생성하면") { - val bonusNumber = BonusNumber(number = Number(number = number)) - - Then("보너스 번호가 생성된다") { - bonusNumber.number shouldBe Number(number = 1) - } - } - } - -}) From 1e2fa7cf6afb4da33e74c1c1595f134a4474d534 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Sun, 10 Dec 2023 22:10:15 +0900 Subject: [PATCH 76/92] =?UTF-8?q?refactor=20:=20=EB=B3=B4=EB=84=88?= =?UTF-8?q?=EC=8A=A4=20=EC=88=AB=EC=9E=90=20=EB=8F=84=EB=A9=94=EC=9D=B8=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20Number=20?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt | 5 ++--- .../kotlin/camp/nextstep/edu/step/step2/view/InputView.kt | 5 ++--- .../nextstep/edu/step/step2/domain/store/LottoStoreTest.kt | 5 ++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt index 481d7015ad..85b5110f9e 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt @@ -1,6 +1,5 @@ package camp.nextstep.edu.step.step2.domain.lotto -import camp.nextstep.edu.step.step2.domain.number.BonusNumber import camp.nextstep.edu.step.step2.domain.number.Number class Lotto( @@ -11,8 +10,8 @@ class Lotto( return numbers.count { targetLotto.numbers.contains(it) } } - fun countMatchBonus(bonusNumber: BonusNumber): Int { - return numbers.count { it.number == bonusNumber.getNumberElement() } + fun countMatchBonus(bonusNumber: Number): Int { + return numbers.count { it.number == bonusNumber.number } } fun getNumberElements(): List { diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt index ae5d9c8a79..c5d6b8a160 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt @@ -2,7 +2,6 @@ package camp.nextstep.edu.step.step2.view import camp.nextstep.edu.step.step2.domain.amount.BuyAmount import camp.nextstep.edu.step.step2.domain.lotto.Lotto -import camp.nextstep.edu.step.step2.domain.number.BonusNumber import camp.nextstep.edu.step.step2.domain.number.Number object InputView { @@ -17,9 +16,9 @@ object InputView { return Lotto.ofInputValues(numbers = readLine()!!) } - fun inputBonusNumber(): BonusNumber { + fun inputBonusNumber(): Number { println("보너스 볼을 입력해 주세요.") - return BonusNumber(number = Number(number = readLine()!!.toInt())) + return Number(number = readLine()!!.toInt()) } } diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt index b8b712f4d7..e5efe70e52 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt @@ -4,7 +4,6 @@ import camp.nextstep.edu.step.step2.domain.amount.BuyAmount import camp.nextstep.edu.step.step2.domain.lotto.Lotto import camp.nextstep.edu.step.step2.domain.lotto.Lottos import camp.nextstep.edu.step.step2.domain.lotto.WinningLotto -import camp.nextstep.edu.step.step2.domain.number.BonusNumber import camp.nextstep.edu.step.step2.domain.number.Number import camp.nextstep.edu.step.step2.domain.result.LottoMatch import camp.nextstep.edu.step.step2.domain.result.LottoResult @@ -55,7 +54,7 @@ class LottoStoreTest : BehaviorSpec({ ) ) - val bonusNumber = BonusNumber(number = Number(number = 7)) + val bonusNumber = Number(number = 7) val winningLotto = WinningLotto( winningLotto = lastWeekWinningLottoLotto, @@ -123,7 +122,7 @@ class LottoStoreTest : BehaviorSpec({ ) ) - val bonusNumber = BonusNumber(number = Number(number = 7)) + val bonusNumber = Number(number = 7) val winningLotto = WinningLotto( winningLotto = lastWeekWinningLottoLotto, From 680efc3ce1e73d2233a40fb6f788d5d009be5565 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Sun, 10 Dec 2023 22:12:53 +0900 Subject: [PATCH 77/92] =?UTF-8?q?refactor=20:=20=EB=8B=B9=EC=B2=A8=20?= =?UTF-8?q?=EB=A1=9C=EB=98=90=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=82=B4,?= =?UTF-8?q?=20=EB=B3=B4=EB=84=88=EC=8A=A4=20=EB=84=98=EB=B2=84=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20=EC=A4=91=EB=B3=B5=20=EC=B2=B4=ED=81=AC?= =?UTF-8?q?=20=EA=B2=80=EC=A6=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nextstep/edu/step/step2/domain/lotto/WinningLotto.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt index b5155c1dfe..aa32108f40 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt @@ -1,14 +1,16 @@ package camp.nextstep.edu.step.step2.domain.lotto -import camp.nextstep.edu.step.step2.domain.number.BonusNumber +import camp.nextstep.edu.step.step2.domain.number.Number data class WinningLotto( val winningLotto: Lotto, - val bonusNumber: BonusNumber + val bonusNumber: Number ) { init { require(winningLotto.numbers.isNotEmpty()) { "당첨번호가 입력되지 않았습니다." } + // winningLotto 내 Number들과 bonusNumber가 중복되는지 검사 + require(!winningLotto.numbers.contains(bonusNumber)) { "보너스 번호는 당첨 번호와 중복될 수 없습니다." } } } From 8efd234c6af3ec47a5d398c70f455774cfa866d3 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Sun, 10 Dec 2023 22:13:11 +0900 Subject: [PATCH 78/92] =?UTF-8?q?test=20:=20=EB=8B=B9=EC=B2=A8=20=EB=A1=9C?= =?UTF-8?q?=EB=98=90=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=82=B4=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=20=EC=B2=B4=ED=81=AC=20=EC=B6=94=EA=B0=80=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B8=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step2/domain/lotto/WinningLottoTest.kt | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt index 9d1de7be2a..4a512888e0 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLottoTest.kt @@ -1,6 +1,5 @@ package camp.nextstep.edu.step.step2.domain.lotto -import camp.nextstep.edu.step.step2.domain.number.BonusNumber import camp.nextstep.edu.step.step2.domain.number.Number import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.BehaviorSpec @@ -10,7 +9,7 @@ import org.junit.jupiter.api.DisplayName @DisplayName("당첨 로또 확인 도메인은") class WinningLottoTest : BehaviorSpec({ - Given("유저 티켓번호들과 이전 당첨 로또가 주어지고") { + Given("당첨 로또 티켓과 보너스 숫자가 주어지고") { val winningLottoRequest = Lotto( listOf( Number(1), @@ -22,7 +21,8 @@ class WinningLottoTest : BehaviorSpec({ ) ) - val bonusNumber = BonusNumber(number = Number(number = 7)) + val bonusNumber = Number(number = 7) + val duplicateBonusNumber = Number(number = 6) When("생성을 요청하면") { val winningLotto = WinningLotto( @@ -39,10 +39,20 @@ class WinningLottoTest : BehaviorSpec({ Number(5), Number(6) ) - - winningLotto.bonusNumber shouldBe BonusNumber(number = Number(number = 7)) + winningLotto.bonusNumber shouldBe Number(number = 7) } + } + When("만약 당첨 로또 숫자들 중 보너스 숫자와 중복이 발생한다면") { + val exceptionByDuplicateBonusNumber = shouldThrow { + WinningLotto( + winningLotto = winningLottoRequest, + bonusNumber = duplicateBonusNumber + ) + } + Then("예외가 발생한다.") { + exceptionByDuplicateBonusNumber.message shouldBe "보너스 번호는 당첨 번호와 중복될 수 없습니다." + } } } @@ -51,7 +61,7 @@ class WinningLottoTest : BehaviorSpec({ listOf() ) - val bonusNumber = BonusNumber(number = Number(number = 7)) + val bonusNumber = Number(number = 7) When("생성 시") { val exceptionByEmptyLotto = shouldThrow { From 98a718c0118d51694d64726cf474c44cdfc207e3 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Sun, 10 Dec 2023 22:13:43 +0900 Subject: [PATCH 79/92] =?UTF-8?q?refactor=20:=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EA=B2=B0=EA=B3=BC=ED=99=95=EC=9D=B8=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lottos 내에서 검증할 수 있도록 수정 진행 --- .../edu/step/step2/domain/lotto/Lottos.kt | 12 ++++++++++ .../edu/step/step2/domain/store/LottoStore.kt | 24 +------------------ 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lottos.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lottos.kt index 9effa22d0c..5bd0e01d7a 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lottos.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lottos.kt @@ -1,5 +1,6 @@ package camp.nextstep.edu.step.step2.domain.lotto +import camp.nextstep.edu.step.step2.domain.result.LottoMatch import java.util.stream.Collectors class Lottos( @@ -10,6 +11,17 @@ class Lottos( require(lottos.isNotEmpty()) { "로또는 1개 이상이어야 합니다." } } + fun checkLottoNumbersByWinningLotto(winningLotto: WinningLotto): List { + val lottoMatchResults = mutableListOf() + + for (lotto in lottos) { + val matchNumbers = lotto.countMatch(winningLotto.winningLotto) + val matchBonus = lotto.countMatchBonus(winningLotto.bonusNumber) + lottoMatchResults.add(LottoMatch.of(matchNumbers, matchBonus)) + } + return lottoMatchResults + } + fun getLottoElements(): List> { return lottos.stream() .map { lotto -> lotto.getNumberElements() } diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt index 729b10bf9b..70d88b6392 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt @@ -4,7 +4,6 @@ import camp.nextstep.edu.step.step2.domain.amount.BuyAmount import camp.nextstep.edu.step.step2.domain.lotto.Lotto import camp.nextstep.edu.step.step2.domain.lotto.Lottos import camp.nextstep.edu.step.step2.domain.lotto.WinningLotto -import camp.nextstep.edu.step.step2.domain.result.LottoMatch import camp.nextstep.edu.step.step2.domain.result.LottoResult import camp.nextstep.edu.step.step2.generator.NumberGenerator @@ -53,10 +52,7 @@ object LottoStore { ticketPrice = LOTTO_TICKET_PRICE ) - val matchResult = lottoWinningResults( - userlottos = userLottos, - winningLotto = winningLotto - ) + val matchResult = userLottos.checkLottoNumbersByWinningLotto(winningLotto = winningLotto) return LottoResult(totalPrice, matchResult) } @@ -68,22 +64,4 @@ object LottoStore { return lottoSize * ticketPrice.toInt() } - /** - * @description : 로또의 결과를 확인합니다. ( 보통 로또 판매처에 내가 구매한 로또들을 넣고 확인하는 방식을 생각했다. ) - */ - private fun lottoWinningResults( - userlottos: Lottos, - winningLotto: WinningLotto - ): List { - val lottoMatchResults = mutableListOf() - - for (lotto in userlottos.lottos) { - val matchNumbers = lotto.countMatch(winningLotto.winningLotto) - val matchBonus = lotto.countMatchBonus(winningLotto.bonusNumber) - lottoMatchResults.add(LottoMatch.of(matchNumbers, matchBonus)) - } - - return lottoMatchResults - } - } From e81166de1f6ee199093342c52a1e1f94e67f67a8 Mon Sep 17 00:00:00 2001 From: Ueibin Kim Date: Sun, 10 Dec 2023 22:14:08 +0900 Subject: [PATCH 80/92] =?UTF-8?q?test=20:=20=EB=A1=9C=EB=98=90=20=EC=9D=BC?= =?UTF-8?q?=EA=B8=89=20=EC=BB=AC=EB=A0=89=EC=85=98=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20(=20Lottos=20)=20=EB=82=B4=20=EB=8B=B9=EC=B2=A8=20?= =?UTF-8?q?=EA=B2=B0=EA=B3=BC=20=ED=99=95=EC=9D=B8=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step2/domain/lotto/LottosTest.kt | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottosTest.kt diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottosTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottosTest.kt new file mode 100644 index 0000000000..fc20c48582 --- /dev/null +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/lotto/LottosTest.kt @@ -0,0 +1,58 @@ +package camp.nextstep.edu.step.step2.domain.lotto + +import camp.nextstep.edu.step.step2.domain.number.Number +import io.kotest.core.annotation.DisplayName +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.assertAll + +@DisplayName("로또 일급 컬렌션은") +class LottosTest : BehaviorSpec ({ + + Given("내가 구매한 로또들과 지난주 당첨 객체가 주어지고") { + val winningLottoRequest = Lotto( + listOf( + Number(1), + Number(2), + Number(3), + Number(4), + Number(5), + Number(6) + ) + ) + + val userLotto = Lotto( + listOf( + Number(1), + Number(2), + Number(3), + Number(4), + Number(5), + Number(6) + ) + ) + + val bonusNumber = Number(number = 7) + + val userLottos = Lottos(lottos = listOf(userLotto)) + + val winningLotto = WinningLotto( + winningLotto = winningLottoRequest, + bonusNumber = bonusNumber + ) + + When("당첨 로또 확인을 요청하면") { + val lottoMatchResults = userLottos.checkLottoNumbersByWinningLotto(winningLotto) + + Then("당첨 결과가 반환된다.") { + assertAll( + { lottoMatchResults.size shouldBe 1}, + { lottoMatchResults[0].matchCount shouldBe 6}, + { lottoMatchResults[0].bonusMatch shouldBe 0}, + { lottoMatchResults[0].prize shouldBe 2_000_000_000} + ) + } + } + } + +}) From 164ebeda1dd80c63bcfb7612c4f8d1dcfbce6250 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 27 Dec 2023 00:29:40 +0900 Subject: [PATCH 81/92] =?UTF-8?q?refactor=20:=20Input=20/=20Output=20View?= =?UTF-8?q?=20=EB=82=B4,=20=EC=88=98=EB=8F=99=20=EA=B5=AC=EB=A7=A4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/nextstep/edu/step/step2/view/InputView.kt | 13 +++++++++++++ .../camp/nextstep/edu/step/step2/view/OutputView.kt | 10 ++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt index c5d6b8a160..0f09585900 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt @@ -1,7 +1,9 @@ package camp.nextstep.edu.step.step2.view import camp.nextstep.edu.step.step2.domain.amount.BuyAmount +import camp.nextstep.edu.step.step2.domain.amount.TicketAmount import camp.nextstep.edu.step.step2.domain.lotto.Lotto +import camp.nextstep.edu.step.step2.domain.lotto.Lottos import camp.nextstep.edu.step.step2.domain.number.Number object InputView { @@ -11,6 +13,17 @@ object InputView { return BuyAmount(readLine()!!.toLong()) } + fun inputManualLottoCount(): TicketAmount { + println("수동으로 구매할 로또 수를 입력해 주세요.") + return TicketAmount(amount = readLine()!!.toLong()) + } + + fun inputManalLottoNumbers(ticketAmount: Long): Lottos { + println("수동으로 구매할 번호를 입력해 주세요.") + val lottoList = (1..ticketAmount).map { Lotto.ofInputValues(numbers = readLine()!!) } + return Lottos(lottos = lottoList) + } + fun inputLastWeekWinningNumbers(): Lotto { println("지난 주 당첨 번호를 입력해 주세요.") return Lotto.ofInputValues(numbers = readLine()!!) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt index 19027e16f5..ad8539ebed 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/view/OutputView.kt @@ -1,15 +1,17 @@ package camp.nextstep.edu.step.step2.view +import camp.nextstep.edu.step.step2.dto.LottoProcessDto import camp.nextstep.edu.step.step2.dto.LottoResultDto object OutputView { - fun displayTicketsNumbers(ticketsAmount: Int, ticketNumbers: List>) { - println("${ticketsAmount}개를 구매했습니다.") + fun displayTicketsNumbers(lottoProcessDto: LottoProcessDto) { + println("수동으로 ${lottoProcessDto.manualTicketAmount}장, 자동으로 ${lottoProcessDto.autoTicketAmount}개를 구매했습니다.") - for (ticketNumber in ticketNumbers) { - println(ticketNumber) + for (lottoTicket in lottoProcessDto.lottoTicketList) { + println(lottoTicket) } + } fun displayLottoResultByDto(lottoResultDto: LottoResultDto) { From 1383fbf4e6b612d8eaa66816675226c17089811f Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 27 Dec 2023 00:30:23 +0900 Subject: [PATCH 82/92] =?UTF-8?q?feat=20:=20=EB=A1=9C=EB=98=90=20=EC=A4=91?= =?UTF-8?q?=EA=B0=84=EA=B2=B0=EA=B3=BC=20=EC=A0=84=EB=8B=AC=EC=9D=84=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20Process=20Dto=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/nextstep/edu/step/step2/dto/LottoProcessDto.kt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/dto/LottoProcessDto.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/dto/LottoProcessDto.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/dto/LottoProcessDto.kt new file mode 100644 index 0000000000..2ff09b8c80 --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/dto/LottoProcessDto.kt @@ -0,0 +1,7 @@ +package camp.nextstep.edu.step.step2.dto + +data class LottoProcessDto( + val manualTicketAmount: Int, + val autoTicketAmount: Int, + val lottoTicketList: List>, +) From 4c17c65fd235024222a0819398b7d85a5754d14a Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 27 Dec 2023 00:31:25 +0900 Subject: [PATCH 83/92] =?UTF-8?q?style=20:=20Code=20Formatter=EB=A5=BC=20?= =?UTF-8?q?=ED=86=B5=ED=95=9C=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step2/domain/result/LottoMatch.kt | 11 ++++++----- .../nextstep/edu/step/step2/dto/LottoResultDto.kt | 4 ++-- .../edu/step/step2/generator/NumberGenerator.kt | 6 ++++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoMatch.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoMatch.kt index 89cc18f701..7786eb7144 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoMatch.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/result/LottoMatch.kt @@ -8,15 +8,16 @@ enum class LottoMatch( SIX_MATCH(6, 0, 2_000_000_000), FIVE_MATCH(5, 0, 1_500_000), FIVE_MATCH_WITH_BONUS(5, 1, 30_000_000), - FOUR_MATCH(4, 0,50_000), - THREE_MATCH(3, 0,5_000), - NONE(0, 0,0); + FOUR_MATCH(4, 0, 50_000), + THREE_MATCH(3, 0, 5_000), + NONE(0, 0, 0); companion object { fun of(matchCount: Int, bonusMatch: Int): LottoMatch { - return values().find { it.matchCount == matchCount && it.bonusMatch == bonusMatch } ?: NONE + return values().find { it.matchCount == matchCount && it.bonusMatch == bonusMatch } + ?: NONE } } - + } diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/dto/LottoResultDto.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/dto/LottoResultDto.kt index f8f13e8ae4..59c5a798cf 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/dto/LottoResultDto.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/dto/LottoResultDto.kt @@ -1,9 +1,9 @@ package camp.nextstep.edu.step.step2.dto -data class LottoResultDto ( +data class LottoResultDto( val matchResponse: List, val lottoProfitRate: Double - ) { +) { data class MatchResponse( val matchCount: Int, diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt index c89716b3f9..8e1e123c69 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/generator/NumberGenerator.kt @@ -5,12 +5,14 @@ import camp.nextstep.edu.step.step2.domain.number.Number enum class NumberGenerator( val generate: (Int, Int) -> List ) { - LOTTO_RANDOM({ startNum, endNum -> (startNum..endNum).shuffled().subList(0, 6).distinct().sorted() }); + LOTTO_RANDOM({ startNum, endNum -> + (startNum..endNum).shuffled().subList(0, 6).distinct().sorted() + }); companion object { fun generate(generator: NumberGenerator, startNumber: Int, endNumber: Int): List { - return generator.generate(startNumber, endNumber).map { Number(it) } + return generator.generate(startNumber, endNumber).map { Number(it) } } } From d0aba478b5fbfa6b78a24803da5e3645ba6824fc Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 27 Dec 2023 00:32:20 +0900 Subject: [PATCH 84/92] =?UTF-8?q?feat=20:=20=EC=88=98=EB=8F=99=20=ED=8B=B0?= =?UTF-8?q?=EC=BC=93=20=EA=B5=AC=EB=A7=A4=EB=A5=BC=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?=EC=88=98=EB=8F=99=20=ED=8B=B0=EC=BC=93=20=EC=88=98=EB=9F=89=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step/step2/domain/amount/ManualTicketAmount.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/main/kotlin/camp/nextstep/edu/step/step2/domain/amount/ManualTicketAmount.kt diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/amount/ManualTicketAmount.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/amount/ManualTicketAmount.kt new file mode 100644 index 0000000000..b69c3575dc --- /dev/null +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/amount/ManualTicketAmount.kt @@ -0,0 +1,12 @@ +package camp.nextstep.edu.step.step2.domain.amount + +@JvmInline +value class ManualTicketAmount( + val amount: Long +) { + + init { + require(amount > 0) { "구매 금액은 0보다 커야 합니다." } + } + +} From b3d6657d5fe8e20d880494d2369d9c2b15a69c9f Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 27 Dec 2023 00:33:00 +0900 Subject: [PATCH 85/92] =?UTF-8?q?refactor=20:=20=EA=B5=AC=EB=A7=A4=20?= =?UTF-8?q?=EC=88=98=EB=9F=89=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=82=B4,?= =?UTF-8?q?=20=EC=88=98=EB=8F=99=20=EC=88=98=EB=9F=89=20=EC=A0=9C=EC=99=B8?= =?UTF-8?q?=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/nextstep/edu/step/step2/domain/amount/BuyAmount.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/amount/BuyAmount.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/amount/BuyAmount.kt index dfa5b555ae..042e17d4c1 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/amount/BuyAmount.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/amount/BuyAmount.kt @@ -12,8 +12,9 @@ value class BuyAmount( constructor(amount: Long) : this(BigDecimal.valueOf(amount)) - fun divideByLotteryPrice(ticketPrice: Long): Int { - return amount.divide(BigDecimal.valueOf(ticketPrice)).toInt() + fun divideByLotteryPriceAndManualLottoAmount(ticketPrice: Long, manualTicketAmount: Int): Int { + val ticketAmount = amount.divide(BigDecimal.valueOf(ticketPrice)).toInt() + return ticketAmount - manualTicketAmount } } From a294b279eea41b96ed2c84bcd212c8146d05b458 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 27 Dec 2023 00:33:39 +0900 Subject: [PATCH 86/92] =?UTF-8?q?refactor=20:=20InputView=20=EB=82=B4=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=84=A4=EC=9E=84=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/camp/nextstep/edu/step/step2/view/InputView.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt index 0f09585900..1ca11cd7e2 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/view/InputView.kt @@ -1,7 +1,7 @@ package camp.nextstep.edu.step.step2.view import camp.nextstep.edu.step.step2.domain.amount.BuyAmount -import camp.nextstep.edu.step.step2.domain.amount.TicketAmount +import camp.nextstep.edu.step.step2.domain.amount.ManualTicketAmount import camp.nextstep.edu.step.step2.domain.lotto.Lotto import camp.nextstep.edu.step.step2.domain.lotto.Lottos import camp.nextstep.edu.step.step2.domain.number.Number @@ -13,9 +13,9 @@ object InputView { return BuyAmount(readLine()!!.toLong()) } - fun inputManualLottoCount(): TicketAmount { + fun inputManualLottoCount(): ManualTicketAmount { println("수동으로 구매할 로또 수를 입력해 주세요.") - return TicketAmount(amount = readLine()!!.toLong()) + return ManualTicketAmount(amount = readLine()!!.toLong()) } fun inputManalLottoNumbers(ticketAmount: Long): Lottos { From 4c32c3f0db3d2328c95ddb32fd00c23b9e437911 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 27 Dec 2023 00:34:20 +0900 Subject: [PATCH 87/92] =?UTF-8?q?refactor=20:=20=EB=8B=B9=EC=B2=A8?= =?UTF-8?q?=EB=B2=88=ED=98=B8,=20=EB=A1=9C=EB=98=90=EB=B2=88=ED=98=B8=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=EA=B2=80=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt | 4 ++++ .../camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt index 85b5110f9e..272299a7cf 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lotto.kt @@ -10,6 +10,10 @@ class Lotto( return numbers.count { targetLotto.numbers.contains(it) } } + fun isDuplicateNumber(anotherNumber: Number): Boolean { + return numbers.contains(anotherNumber) + } + fun countMatchBonus(bonusNumber: Number): Int { return numbers.count { it.number == bonusNumber.number } } diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt index aa32108f40..58d4806e50 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/WinningLotto.kt @@ -10,7 +10,7 @@ data class WinningLotto( init { require(winningLotto.numbers.isNotEmpty()) { "당첨번호가 입력되지 않았습니다." } // winningLotto 내 Number들과 bonusNumber가 중복되는지 검사 - require(!winningLotto.numbers.contains(bonusNumber)) { "보너스 번호는 당첨 번호와 중복될 수 없습니다." } + require(!winningLotto.isDuplicateNumber(bonusNumber)) { "보너스 번호는 당첨 번호와 중복될 수 없습니다." } } } From 8b19699fc0b21b3437518f732828a8abe268eaf0 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 27 Dec 2023 00:35:11 +0900 Subject: [PATCH 88/92] =?UTF-8?q?refactor=20:=20Lottos=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EB=82=B4,=20mutableListOf=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95,=20=EC=88=98=EB=8F=99=20?= =?UTF-8?q?=EC=88=AB=EC=9E=90=20=EA=B2=80=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nextstep/edu/step/step2/domain/lotto/Lottos.kt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lottos.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lottos.kt index 5bd0e01d7a..9c1567cc00 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lottos.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/lotto/Lottos.kt @@ -1,5 +1,6 @@ package camp.nextstep.edu.step.step2.domain.lotto +import camp.nextstep.edu.step.step2.domain.number.Number import camp.nextstep.edu.step.step2.domain.result.LottoMatch import java.util.stream.Collectors @@ -11,15 +12,16 @@ class Lottos( require(lottos.isNotEmpty()) { "로또는 1개 이상이어야 합니다." } } - fun checkLottoNumbersByWinningLotto(winningLotto: WinningLotto): List { - val lottoMatchResults = mutableListOf() + fun isContainLottoNumbers(numbers: List): Boolean { + return lottos.contains(Lotto(numbers = numbers)) + } - for (lotto in lottos) { + fun checkLottoNumbersByWinningLotto(winningLotto: WinningLotto): List { + return lottos.map { lotto -> val matchNumbers = lotto.countMatch(winningLotto.winningLotto) val matchBonus = lotto.countMatchBonus(winningLotto.bonusNumber) - lottoMatchResults.add(LottoMatch.of(matchNumbers, matchBonus)) + LottoMatch.of(matchNumbers, matchBonus) } - return lottoMatchResults } fun getLottoElements(): List> { From b154b18d60b14a93ab00e9fcb5b4a252e0ba7ae8 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 27 Dec 2023 00:35:50 +0900 Subject: [PATCH 89/92] =?UTF-8?q?refactor=20:=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EC=83=81=EC=A0=90=20=EB=82=B4,=20=EC=88=98=EB=8F=99=20?= =?UTF-8?q?=EA=B5=AC=EB=A7=A4=20=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EB=A1=9C=EC=A7=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EC=A7=84=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/step/step2/domain/store/LottoStore.kt | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt index 70d88b6392..ab7e67f7bc 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStore.kt @@ -20,20 +20,31 @@ object LottoStore { /** * @description : 구매금액에 따른 로또 티켓 수량을 구한다. */ - fun buyLottoTickets(buyAmount: BuyAmount): LottoTicketAmount { - val lottoTicketAmount = buyAmount.divideByLotteryPrice(ticketPrice = LOTTO_TICKET_PRICE) + fun buyAutoLottoTickets(buyAmount: BuyAmount, manualTicketAmount: Int): LottoTicketAmount { + val lottoTicketAmount = buyAmount.divideByLotteryPriceAndManualLottoAmount( + ticketPrice = LOTTO_TICKET_PRICE, + manualTicketAmount = manualTicketAmount + ) + return LottoTicketAmount(lottoTicketAmount) } /** * @description : 로또 티켓 수량에 따른 로또 번호를 생성한다. */ - fun createNumbersByLottoTicketAmount(ticketAmount: LottoTicketAmount): Lottos { + fun createNumbersByLottoTicketAmount( + ticketAmount: LottoTicketAmount, + manualLottos: Lottos + ): Lottos { val lottoTickets = mutableListOf() for (i in 1..ticketAmount.lottoTicketAmount) { - val numbers = NumberGenerator.generate(NumberGenerator.LOTTO_RANDOM, START_NUMBER, END_NUMBER) - lottoTickets.add(Lotto(numbers = numbers)) + val numbers = + NumberGenerator.generate(NumberGenerator.LOTTO_RANDOM, START_NUMBER, END_NUMBER) + + if (!manualLottos.isContainLottoNumbers(numbers)) { + lottoTickets.add(Lotto(numbers = numbers)) + } } return Lottos(lottos = lottoTickets) From 6d68d71a3a6645f9125dd053d126fb981233b368 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 27 Dec 2023 00:36:18 +0900 Subject: [PATCH 90/92] =?UTF-8?q?test=20:=20=EA=B5=AC=EC=9E=85=EA=B8=88?= =?UTF-8?q?=EC=95=A1,=20=EB=A1=9C=EB=98=90=20=EA=B0=9C=EC=88=98=EB=A5=BC?= =?UTF-8?q?=20=ED=86=B5=ED=95=9C=20=EA=B5=AC=EB=A7=A4=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=A7=84=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../step/step2/domain/store/LottoStoreTest.kt | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt index e5efe70e52..032c687f2e 100644 --- a/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt +++ b/src/test/kotlin/camp/nextstep/edu/step/step2/domain/store/LottoStoreTest.kt @@ -15,14 +15,15 @@ import java.math.BigDecimal @DisplayName("로또 상점은") class LottoStoreTest : BehaviorSpec({ - Given("구입 금액이 주어지고") { + Given("구입 금액과 수동 로또 개수가 주어지고") { val buyAmount = BuyAmount(amount = BigDecimal.valueOf(10000L)) + val manualTicketAmount = 2 When("로또를 구매하면") { - val lottoTickets = LottoStore.buyLottoTickets(buyAmount) + val lottoTickets = LottoStore.buyAutoLottoTickets(buyAmount, manualTicketAmount) Then("구매한 금액만큼의 로또 티켓 수를 반환한다.") { - lottoTickets.lottoTicketAmount shouldBe 10 + lottoTickets.lottoTicketAmount shouldBe 8 } } } @@ -82,12 +83,24 @@ class LottoStoreTest : BehaviorSpec({ } } - Given("로또의 수량이주어지고") { + Given("로또의 수량과 수동 로또번호가 주어지고") { val lottoTicketAmount = LottoTicketAmount(lottoTicketAmount = 10) + val manualLotto = Lottos( lottos = listOf( + Lotto( + listOf( + Number(number = 1), + Number(number = 2), + Number(number = 3), + Number(number = 4), + Number(number = 5), + Number(number = 6) + ) + ) + )) When("로또 발급을 시도하면") { val lottoTickets = - LottoStore.createNumbersByLottoTicketAmount(ticketAmount = lottoTicketAmount) + LottoStore.createNumbersByLottoTicketAmount(ticketAmount = lottoTicketAmount, manualLottos = manualLotto) Then("구매한 수량만큼의 로또가 발급된다.") { lottoTickets.lottos.size shouldBe 10 @@ -148,5 +161,4 @@ class LottoStoreTest : BehaviorSpec({ } } } - }) From a9f8131af01194d8d96eb77232c84cf7f0d9673a Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 27 Dec 2023 00:36:40 +0900 Subject: [PATCH 91/92] =?UTF-8?q?refactor=20:=20=EC=88=98=EB=8F=99=20?= =?UTF-8?q?=EB=A1=9C=EB=98=90=20=EA=B5=AC=EB=A7=A4=EB=A5=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=ED=95=9C=20main=20=ED=95=A8=EC=88=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../camp/nextstep/edu/step/step2/main.kt | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt b/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt index 216e548566..b4f1a53f80 100644 --- a/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt +++ b/src/main/kotlin/camp/nextstep/edu/step/step2/main.kt @@ -4,28 +4,40 @@ import camp.nextstep.edu.step.step2.domain.amount.BuyAmount import camp.nextstep.edu.step.step2.domain.lotto.Lottos import camp.nextstep.edu.step.step2.domain.lotto.WinningLotto import camp.nextstep.edu.step.step2.domain.store.LottoStore +import camp.nextstep.edu.step.step2.dto.LottoProcessDto import camp.nextstep.edu.step.step2.view.InputView import camp.nextstep.edu.step.step2.view.OutputView fun main() { val buyAmount = InputView.getInputValueAndReturnBuyAmount() + val manualLottoCount = InputView.inputManualLottoCount() + val manualLottos = InputView.inputManalLottoNumbers(ticketAmount = manualLottoCount.amount) - val lottos = buyLottoTicketsWithAmount(buyAmount = buyAmount) + val lottos = buyLottoTicketsWithAmount(buyAmount = buyAmount, manualLottos = manualLottos) checkLottoTicketsWinningResult(lottos = lottos) } -private fun buyLottoTicketsWithAmount(buyAmount: BuyAmount): Lottos { - val tickets = LottoStore.buyLottoTickets(buyAmount = buyAmount) - - val lottos = LottoStore.createNumbersByLottoTicketAmount(ticketAmount = tickets) +private fun buyLottoTicketsWithAmount(buyAmount: BuyAmount, manualLottos: Lottos): Lottos { + val tickets = LottoStore.buyAutoLottoTickets( + buyAmount = buyAmount, + manualTicketAmount = manualLottos.getLottoSize() + ) + val lottos = LottoStore.createNumbersByLottoTicketAmount( + ticketAmount = tickets, + manualLottos = manualLottos + ) - val ticketElements = lottos.getLottoElements() + val autoLottoNumbers = lottos.getLottoElements() + val manualLottoNumbers = manualLottos.getLottoElements() OutputView.displayTicketsNumbers( - ticketsAmount = tickets.lottoTicketAmount, - ticketNumbers = ticketElements + LottoProcessDto( + manualTicketAmount = manualLottos.getLottoSize(), + autoTicketAmount = tickets.lottoTicketAmount, + lottoTicketList = manualLottoNumbers + autoLottoNumbers + ) ) return lottos From 2fa0905b9cf0dd5d6e4939a3e3f34bb4251f8da0 Mon Sep 17 00:00:00 2001 From: kimueibin Date: Wed, 27 Dec 2023 00:36:56 +0900 Subject: [PATCH 92/92] =?UTF-8?q?feat=20:=20step4=20=EB=A1=9C=EB=98=90=20?= =?UTF-8?q?=EC=88=98=EB=8F=99=20=EA=B5=AC=EB=A7=A4=20readme=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index e63ac69cfc..434e9d42f7 100644 --- a/README.md +++ b/README.md @@ -52,3 +52,9 @@ 추가한 도메인 - 보너스 숫자 ( BonusNumber ) +# Step4 - 로또 수동 구매 ( Lotto ) +추가적인 요구사항 +- 사용자가 수동으로 추첨번호를 입력할 수 있도록 해야한다. +- 입력한 금액, 자동 생성 숫자, 수동 생성 번호를 입력하도록 해야한다. +- 수동 생성 번호는 자동 생성 번호와 중복될 수 없다. +- 구매한 금액에서 수동 생성한 티켓을 제외한 나머지가 생성되어야 한다.