Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Step2] 2단계 - 로또(자동) #1139

Merged
merged 13 commits into from
Dec 31, 2024
7 changes: 1 addition & 6 deletions src/main/kotlin/lotto/Application.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package lotto

import lotto.domain.Lotto
import lotto.domain.LottoCalculator
import lotto.domain.LottoMaker
import lotto.domain.LottoTicket
import lotto.ui.InputView
import lotto.ui.ResultView
Expand All @@ -12,11 +11,7 @@ fun main() {
val resultView = ResultView()

val amount = inputView.getMoney()
val lottoCount = amount / 1000
val lottoMaker = LottoMaker()

val tickets = List(lottoCount) { lottoMaker.makeLotto() }
val lottoTicket = LottoTicket(tickets)
val lottoTicket = LottoTicket.makeTicket(amount)
resultView.printTickets(lottoTicket.getTickets())

val winningLotto = Lotto(inputView.getWinningNumbers())
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/lotto/domain/Lotto.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package lotto.domain

data class Lotto(val numbers: List<Int>) {
init {
require(numbers.size == 6) {"Invalid input"}
require(numbers.size == 6) { "Invalid input" }
require(numbers.all { it in 1..45 }) { "Out of Range" }
}

fun getMatchedNumberCount(winningLotto: Lotto): Int {
return numbers.count { it in winningLotto}
return numbers.count { it in winningLotto }
}

operator fun contains(number: Int): Boolean {
Expand Down
29 changes: 29 additions & 0 deletions src/main/kotlin/lotto/domain/LottoCalculator.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package lotto.domain

class LottoCalculator {
Copy link
Member

Choose a reason for hiding this comment

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

LottoCalculator라는 이름만 보고도 현재 하고 있는 행동(수익률 계산, 로또 결과 판단)을 예측할 수 있을까요?

Copy link
Member

Choose a reason for hiding this comment

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

여러 가지 해결 방법이 있겠지만, 잘 Wrapping해주신 LottoResult를 외부에서 생성해주지 말고, 객체 스스로 판단하여 Result를 생성할 수 있도록 만드는 것도 하나의 방법이 될 수 있을 것 같아요 🙂

fun calculateResults(
tickets: LottoTicket,
winningNumbers: Lotto,
): LottoResult {
return LottoResult(
tickets.getTickets()
.groupingBy { it.getMatchedNumberCount(winningNumbers) }
.eachCount(),
)
}

fun calculateProfit(lottoResult: LottoResult): Double {
val totalPrize =
lottoResult.getResults().entries.sumOf { (match, count) ->
when (match) {
3 -> 5000 * count
4 -> 50000 * count
5 -> 1500000 * count
6 -> 2000000000 * count
else -> 0
}
}
Comment on lines +17 to +25
Copy link
Member

Choose a reason for hiding this comment

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

다음 단계를 진행하시면서 아래 요구 사항에 맞게 enum 클래스를 활용해 보시고 이전과 어떻게 달라졌는지 직접 확인해보시면 더욱 의미있을 것 같아요!

Enum 클래스를 적용해 프로그래밍을 구현한다.


return totalPrize.toDouble()
}
}
14 changes: 9 additions & 5 deletions src/main/kotlin/lotto/domain/LottoMaker.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package lotto.domain

class LottoMaker {
class LottoMaker(private val numberGenerator: () -> List<Int>) {
fun makeLotto(): Lotto {
return Lotto((START_NUMBER..END_NUMBER).shuffled().take(LOTTO_COUNT).sorted())
return Lotto(numberGenerator().sorted())
}

companion object {
const val START_NUMBER = 1
const val END_NUMBER = 45
const val LOTTO_COUNT = 6
private const val START_NUMBER = 1
private const val END_NUMBER = 45
private const val LOTTO_COUNT = 6

fun defaultMaker(): LottoMaker {
return LottoMaker({ (START_NUMBER..END_NUMBER).shuffled().take(LOTTO_COUNT).sorted() })
}
}
}
11 changes: 11 additions & 0 deletions src/main/kotlin/lotto/domain/LottoResult.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package lotto.domain

data class LottoResult(private val result: Map<Int, Int>) {
fun getResults(): Map<Int, Int> {
return result
}

fun getMatchCount(match: Int): Int {
return result.getOrDefault(match, 0)
}
}
9 changes: 9 additions & 0 deletions src/main/kotlin/lotto/domain/LottoTicket.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,14 @@ package lotto.domain

class LottoTicket(private val tickets: List<Lotto>) {
fun size(): Int = tickets.size

fun getTickets(): List<Lotto> = tickets

companion object {
fun makeTicket(amount: Int): LottoTicket {
val lottoMaker = LottoMaker.defaultMaker()
val lottoCount = amount / 1000
return LottoTicket(List(lottoCount) { lottoMaker.makeLotto() })
Copy link
Member

Choose a reason for hiding this comment

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

리뷰를 잘 반영해서 도메인 로직을 도메인 객체에 잘 위임해주셨어요!
이러한 로직을 부생성자로 만드는 것도 충분히 고려해볼 수 있을 것 같은데요,
부생성자에 대한 아래와 같은 시각도 있으니 참고해보시면 도움이 되실 것 같습니다 🙂

Copy link
Member

Choose a reason for hiding this comment

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

더불어 이 로직도 테스트 코드로 검증해보면 어떨까요?

}
}
}
5 changes: 3 additions & 2 deletions src/main/kotlin/lotto/ui/ResultView.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package lotto.ui

import lotto.domain.Lotto
import lotto.domain.LottoResult

class ResultView {
fun printTickets(tickets: List<Lotto>) {
Expand All @@ -9,12 +10,12 @@ class ResultView {
}

fun printResults(
results: Map<Int, Int>,
results: LottoResult,
profit: Double,
) {
println("당첨 통계")
println("---------")
results.forEach { (matchCount, count) ->
results.getResults().forEach { (matchCount, count) ->
println("$matchCount 개 일치 - $count 개")
}
println("총 수익률은 $profit 입니다.")
Expand Down
36 changes: 20 additions & 16 deletions src/test/kotlin/lotto/domain/LottoCalculatorTest.kt
Original file line number Diff line number Diff line change
@@ -1,36 +1,40 @@
package lotto.domain

import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test

class LottoCalculatorTest {
private val calculator = LottoCalculator()
Copy link
Member

Choose a reason for hiding this comment

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

LottoCalculator는 커밋되지 않은 것 같아요!

Copy link
Author

Choose a reason for hiding this comment

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

빠졌었네요ㅠ 추가로 커밋했습니다!


@Test
fun testLottoCalculator() {
val tickets = LottoTicket(
listOf(
Lotto(listOf(1, 2, 3, 4, 5, 6)),
Lotto(listOf(1, 2, 3, 7, 8, 9)),
Lotto(listOf(10, 11, 12, 13, 14, 15))
val tickets =
LottoTicket(
listOf(
Lotto(listOf(1, 2, 3, 4, 5, 6)),
Lotto(listOf(1, 2, 3, 7, 8, 9)),
Lotto(listOf(10, 11, 12, 13, 14, 15)),
)
)
)
val winningLotto = Lotto(listOf(1, 2, 3, 4, 5, 6))

val results = calculator.calculateResults(tickets, winningLotto)
assertEquals(1, results[6])
assertEquals(1, results[3])
assertEquals(1, results[0])
assertEquals(1, results.getMatchCount(6))
assertEquals(1, results.getMatchCount(3))
assertEquals(1, results.getMatchCount(0))
}

@Test
fun testCalculateProfit() {
val results = mapOf(
6 to 1,
5 to 2,
4 to 1,
3 to 2
)
val results =
LottoResult(
mapOf(
6 to 1,
5 to 2,
4 to 1,
3 to 2,
)
)

val profit = calculator.calculateProfit(results)
assertEquals(
Expand Down
25 changes: 18 additions & 7 deletions src/test/kotlin/lotto/domain/LottoMakerTest.kt
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
package lotto.domain

import io.kotest.matchers.shouldBe
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Assertions.*

class LottoMakerTest {
@Test
fun `Lotto - size shoule be 6`() {
val lottoMaker = LottoMaker()
fun `Lotto - size should be 6`() {
val fixedNumbers = listOf(1, 2, 3, 4, 5, 6)
val lottoMaker = LottoMaker { fixedNumbers }
val lotto = lottoMaker.makeLotto()
assertEquals(6, lotto.numbers.size)

lotto.numbers.size shouldBe 6
}

@Test
fun `Lotto - should be same with list`() {
val fixedNumbers = listOf(1, 2, 3, 4, 5, 6)
val lottoMaker = LottoMaker { fixedNumbers }
val lotto = lottoMaker.makeLotto()

lotto.numbers shouldBe fixedNumbers
}

@Test
fun `Lotto - shoule be in range(1-45)`() {
val lottoMaker = LottoMaker()
fun `Lotto - should be in range(1-45)`() {
val lottoMaker = LottoMaker.defaultMaker()
val lotto = lottoMaker.makeLotto()
assertTrue(lotto.numbers.all { it in 1..45 })
lotto.numbers.all { it in 1..45 } shouldBe true
}
}