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

4단계 - 로또(수동) #1128

Open
wants to merge 21 commits into
base: pablo730
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
3069eaa
미션1 초기 세팅 및 테스트 실패 코드 작성
Pablo730 Nov 22, 2024
d054953
Merge remote-tracking branch 'upstream/pablo730'
Pablo730 Nov 30, 2024
fe63e9c
Merge remote-tracking branch 'upstream/pablo730'
Pablo730 Dec 1, 2024
24366d5
리뷰 반영 - 메서드명 개선, enum 활용, 패키지 위치 수정, 테스트 코드 개선 등
Pablo730 Dec 1, 2024
aae3346
테스트 코드 수정
Pablo730 Dec 1, 2024
c5e0aad
2단계 피드백 반영
Pablo730 Dec 1, 2024
6b7731b
Merge remote-tracking branch 'upstream/pablo730'
Pablo730 Dec 9, 2024
7da206a
lottoTicket 수동 로또, 자동 로또 sealed class 활용 및 테스트 수정
Pablo730 Dec 13, 2024
83f7e25
lottoTicket들을 관리하는 일급 컬렉션 LottoTickets 추가
Pablo730 Dec 13, 2024
c5e6441
로또 번호 자동 생성 로직 분리
Pablo730 Dec 13, 2024
38ef9bf
로또 구입 비용을 토대로 로또 구매 계산 클래스 분리 LottoPurchaseCalculator
Pablo730 Dec 13, 2024
69907e7
일급 컬렉션 LottoTickets 추가에 따른 코드 수정
Pablo730 Dec 13, 2024
7c6c04f
불필요한 PurchasedLottoTickets 삭제에 따른 코드 수정
Pablo730 Dec 13, 2024
47ff7e3
LottoNumberGenerator 코드 수정에 따른 테스트 수정
Pablo730 Dec 13, 2024
feb0e89
자동 로또 발급 기능에 대한 AutoLottoIssuer 클래스 구현 및 테스트
Pablo730 Dec 13, 2024
9da2ccd
수동 로또 구입 view 구현 및 로또 번호 split util 분리
Pablo730 Dec 13, 2024
b702361
수동 구매 반영에 따른 PurchaseLottoView 수정
Pablo730 Dec 13, 2024
13016fd
Controller 수동 구매 로또 메서드 추가 및 기존 메서드 분리
Pablo730 Dec 13, 2024
d56c98a
리류 반영 -> collection에서 더 직관적인 kotest 함수로 변경
Pablo730 Dec 16, 2024
7ab86bb
리뷰 반영, AutoLottoTicket 클래스 - 불필요한 프로퍼티 선언 제거
Pablo730 Dec 16, 2024
a80a788
리뷰 반영 - 리스트 초기화 로직 활용으로 간결하게 표현
Pablo730 Dec 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
- 로또 1장의 가격은 1,000원이다.
- 2등을 위해 추가 번호를 하나 더 추첨한다.
- 당첨 통계에 2등도 추가해야 한다.

- 현재 로또 생성기는 자동 생성 기능만 제공한다. 사용자가 수동으로 추첨 번호를 입력할 수 있도록 해야 한다.
- 입력한 금액, 자동 생성 숫자, 수동 생성 번호를 입력하도록 해야 한다.
-
## 기능 설계
- [x] 로또 번호는 1부터 45사이 값이 아니면 에러가 발생한다
- [x] 로또 번호는 value class로 관리된다
Expand All @@ -13,9 +15,9 @@
- [x] 비용을 지불해 한번에 여러장 로또를 구입할 수 있다
- [x] 로또 구입 비용이 1,000원 미만일 경우 에러가 발생한다
- [x] 로또 구입 비용이 1,000원 단위가 아닐 경우 에러가 발생한다
- [x] 로또 구입 비용에 대해 몇 장의 로또가 구입 됐는지 확인활 수 있다
- [x] 로또 번호가 1부터 45사이의 숫자가 아니면 에러가 발생한다
- [x] 로또 번호를 6개로 지정할 경우가 아니면 에러가 발생한다 (예를 들어 5개 또는 7개)
- [x] 로또 구입 비용에 대해 몇 장의 로또가 구입될 수 있는지 확인활 수 있다
- [x] 로또 번호를 수동으로 부여할 수 있다
- [x] 수동 로또를 여러개 구입할 수 있다
- [x] 로또 번호를 자동으로 부여한다
- [x] 로또 번호는 1부터 45사이의 중복되지 않는 숫자 6개로 이루어져야한다
- [x] 로또 당첨 번호를 입력할 수 있다
Expand Down
7 changes: 5 additions & 2 deletions src/main/kotlin/lotto/application/LottoApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ package lotto.application
import lotto.controller.LottoController

fun main() {
val purchasedLottoTickets = LottoController.purchaseLotto()
val maxPurchaseLottoCount = LottoController.getMaxPurchaseLottoCountFromPayment()
val manualLottoTickets = LottoController.purchaseManualLotto(maxPurchaseLottoCount)
val totalLottoTickets = LottoController.createAutoLotto(maxPurchaseLottoCount, manualLottoTickets)
val lottoWinnerNumbers = LottoController.createWinningLottoNumbers()
LottoController.resultPayout(purchasedLottoTickets = purchasedLottoTickets, lottoWinnerNumbers = lottoWinnerNumbers)

LottoController.resultPayout(lottoTickets = totalLottoTickets, lottoWinnerNumbers = lottoWinnerNumbers)
}
49 changes: 34 additions & 15 deletions src/main/kotlin/lotto/controller/LottoController.kt
Original file line number Diff line number Diff line change
@@ -1,40 +1,59 @@
package lotto.controller

import lotto.domain.LottoNumber
import lotto.domain.LottoNumbers
import lotto.domain.LottoTicketIssuer
import lotto.domain.AutoLottoIssuer
import lotto.domain.LottoNumberGenerator
import lotto.domain.LottoPurchaseCalculator
import lotto.domain.LottoTickets
import lotto.domain.LottoWinnerNumbers
import lotto.domain.PurchasedLottoTickets
import lotto.domain.generateLottoNumbers
import lotto.view.LottoPayoutView
import lotto.view.PurchaseLottoResultView
import lotto.view.ManualLottoView
import lotto.view.PurchaseLottoView
import lotto.view.WinnerLottoNumberView

object LottoController {
fun purchaseLotto(): PurchasedLottoTickets {
fun getMaxPurchaseLottoCountFromPayment(): Int {
val amountPaid = PurchaseLottoView.inputPurchaseCost()
return LottoPurchaseCalculator.getMaxPurchasedLottoTicketCount(amountPaid)
}

fun purchaseManualLotto(maxPurchaseLottoCount: Int): LottoTickets {
val manualLottoCount = ManualLottoView.inputManualLottoCount(maxPurchaseLottoCount)
return ManualLottoView.repeatInputManualLottoNumbers(manualLottoCount)
}

val purchasedLottoTickets =
LottoTicketIssuer.issueTickets(amountPaid = amountPaid, generateLottoNumbers = { generateLottoNumbers() })
fun createAutoLotto(
maxPurchaseLottoCount: Int,
manualLottoTickets: LottoTickets,
): LottoTickets {
val autoLottoCount = maxPurchaseLottoCount - manualLottoTickets.lottoTickets.size

PurchaseLottoResultView.displayPurchaseLottoResults(purchasedLottoTickets = purchasedLottoTickets)
val autoLottoTickets =
AutoLottoIssuer.issueAutoLottoTickets(autoLottoCount) {
LottoNumberGenerator.generateAutoLottoNumbers()
}

return purchasedLottoTickets
PurchaseLottoView.displayPurchasedLottosView(
manualLottoTickets = manualLottoTickets,
autoLottoTickets = autoLottoTickets,
)

val combinedManualLottoAndAutoLotto = manualLottoTickets.lottoTickets.plus(autoLottoTickets.lottoTickets)

return LottoTickets(combinedManualLottoAndAutoLotto)
Copy link

Choose a reason for hiding this comment

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

마지막 return전까지 자동 LottoTickets객체와 수동 LottoTickets객체가 유의미하게 쓰인적이 없는것같아요!! (전부다 lottoTickets 프로퍼티를 꺼내서 검증을 진행했네요!)

자동, 수동 LottoTickets객체를 미리 만들 필요가 있는지 고민해보면 좋을 것 같습니다!

}

fun createWinningLottoNumbers(): LottoWinnerNumbers {
val inputLottoNumbers = WinnerLottoNumberView.inputWinningLottoNumbers()
val lottoNumbers = LottoNumbers(inputLottoNumbers.map { LottoNumber.of(it) }.toSet())
val inputBonusNumber = WinnerLottoNumberView.inputBonusNumber()
return LottoWinnerNumbers(lottoNumbers = lottoNumbers, bonusNumber = LottoNumber.of(inputBonusNumber))

return LottoWinnerNumbers(lottoNumbers = inputLottoNumbers, bonusNumber = inputBonusNumber)
}

fun resultPayout(
purchasedLottoTickets: PurchasedLottoTickets,
lottoTickets: LottoTickets,
lottoWinnerNumbers: LottoWinnerNumbers,
) {
val purchasedLottoResults = lottoWinnerNumbers.resultLottoPayout(purchasedLottoTickets)
val purchasedLottoResults = lottoWinnerNumbers.resultLottoPayout(lottoTickets)
return LottoPayoutView.displayWinningStatistics(purchasedLottoResults = purchasedLottoResults)
}
}
14 changes: 14 additions & 0 deletions src/main/kotlin/lotto/domain/AutoLottoIssuer.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package lotto.domain

object AutoLottoIssuer {
fun issueAutoLottoTickets(
autoLottoCount: Int,
generateLottoNumbers: () -> LottoNumbers,
): LottoTickets {
val autoLottoTickets = mutableListOf<LottoTicket.AutoLottoTicket>()

repeat(autoLottoCount) { autoLottoTickets.add(LottoTicket.AutoLottoTicket { generateLottoNumbers() }) }

return LottoTickets(autoLottoTickets)
}
}
15 changes: 9 additions & 6 deletions src/main/kotlin/lotto/domain/LottoNumberGenerator.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package lotto.domain

import lotto.domain.LottoNumber.Companion.LOTTO_NUMBER_MAX_VALUE
import lotto.domain.LottoNumber.Companion.LOTTO_NUMBER_MIN_VALUE
import lotto.domain.LottoNumbers.Companion.LOTTO_NUMBER_COUNT
object LottoNumberGenerator {
fun generateAutoLottoNumbers(): LottoNumbers {
val randomNumbers = generatorRandomNumber()
return LottoNumbers(randomNumbers.map { LottoNumber.of(it) }.toSet())
}

fun generateLottoNumbers(): Set<Int> {
return (LOTTO_NUMBER_MIN_VALUE..LOTTO_NUMBER_MAX_VALUE)
.toSet().shuffled().take(LOTTO_NUMBER_COUNT).sorted().toSet()
fun generatorRandomNumber(): List<Int> {
return (LottoNumber.LOTTO_NUMBER_MIN_VALUE..LottoNumber.LOTTO_NUMBER_MAX_VALUE)
.shuffled().take(LottoNumbers.LOTTO_NUMBER_COUNT).sorted()
}
}
18 changes: 18 additions & 0 deletions src/main/kotlin/lotto/domain/LottoPurchaseCalculator.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package lotto.domain

object LottoPurchaseCalculator {
fun getMaxPurchasedLottoTicketCount(amountPaid: Int): Int {
checkAmountPaid(amountPaid)
return amountPaid / DEFAULT_LOTTO_PRICE
}

private fun checkAmountPaid(amountPaid: Int) {
require(amountPaid >= DEFAULT_LOTTO_PRICE) { INVALID_MIN_COST_LOTTO_PAID_MESSAGE }
require(amountPaid % DEFAULT_LOTTO_PRICE == CHECK_SURPLUS) { INVALID_THOUSAND_UNIT_LOTTO_PAID_MESSAGE }
}

const val DEFAULT_LOTTO_PRICE: Int = 1000
private const val CHECK_SURPLUS: Int = 0
private const val INVALID_MIN_COST_LOTTO_PAID_MESSAGE: String = "로또 구입 비용은 최소 1,000원 이상 이어야 합니다"
private const val INVALID_THOUSAND_UNIT_LOTTO_PAID_MESSAGE: String = "로또 구입 비용은 1,000원 단위로 지불해야 합니다"
}
10 changes: 8 additions & 2 deletions src/main/kotlin/lotto/domain/LottoTicket.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package lotto.domain

data class LottoTicket(private val generateLottoNumbers: () -> Set<Int>) {
val lottoNumbers = LottoNumbers(generateLottoNumbers().map { LottoNumber.of(it) }.toSet())
sealed class LottoTicket {
Copy link

Choose a reason for hiding this comment

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

sealed class 👍

sealed interface도 있는데 sealed class로 작성하신 이유와 이를 나누는 기준이 있을까요? (질문입니다!!)

Copy link
Author

Choose a reason for hiding this comment

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

sealed class인 LottoTicket은 상속을 통해 구체적인 구현체인 ManualLottoTicket과 AutoLottoTicket이 공통적으로 사용할 수 있는 메서드(checkLottoWinnerRank)를 제공하고 있는데요.

이처럼 구현체 간에 공통 기능이나 상태를 정의해야 할 때 sealed interface 보단 sealed class가 적합하다고 판단했습니다

만약, 클래스 내부에서 공유할 구체적인 구현이나 상태가 없다면, 특정 메서드를 구현하도록 강제하는 sealed interface를 고려했을 것 같습니다

sealed class와 sealed interface 둘 중에 무엇이 더 적절한지 다시 한번 생각해 볼 수 있는 좋은 질문을 주셔서 감사합니다!

혹시 다른 의견 있다면 피드백 부탁드립니다 🙇

abstract val lottoNumbers: LottoNumbers

fun checkLottoWinnerRank(lottoWinnerNumbers: LottoWinnerNumbers): LottoWinnerRank {
val matchCount = lottoNumbers.checkLottoNumbersMatch(lottoWinnerNumbers.lottoNumbers)
val bonusCheck = lottoNumbers.contains(lottoWinnerNumbers.bonusNumber)
return LottoWinnerRank.getRankByMatches(matchCount = matchCount, bonusCheck = bonusCheck)
}

class ManualLottoTicket(override val lottoNumbers: LottoNumbers) : LottoTicket()
Copy link

Choose a reason for hiding this comment

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

nested class로 선언하고 상속하신 이유가 있을까요??

Copy link
Author

Choose a reason for hiding this comment

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

당시 다른 로직에 신경쓰느라 이 부분은 깊게 고민하지 못하고 자연스럽게 nested class로 선언하게 된 것 같은데요 😢

다시 한번 nested class로 선언하게 된 주된 이유를 떠올려 봤을 때,

기능 구현상 LottoTicket과 관련된 클래스가 수동 로또, 자동 로또만 고려될 수 있고,

LottoTicket의 checkLottoWinnerRank 메서드 외에 하위 클래스별로 서로 다른 메서드가 존재하지 않아

외부 클래스보다 nested class로 구현된 코드가 좀 더 이해하기 쉽고 관리하기가 용이할 것으로 판단한 것 같습니다

혹시 다른 의견이 있다면 말씀부탁드립니다!


class AutoLottoTicket(private val generateLottoNumbers: () -> LottoNumbers) : LottoTicket() {
Copy link

Choose a reason for hiding this comment

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

generateLottoNumbers는 프로퍼티는 아닌걸로 보이네요! :)

Suggested change
class AutoLottoTicket(private val generateLottoNumbers: () -> LottoNumbers) : LottoTicket() {
class AutoLottoTicket(generateLottoNumbers: () -> LottoNumbers) : LottoTicket() {

Copy link
Author

Choose a reason for hiding this comment

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

해당 함수는 AutoLottoTicket 생성 시점에만 호출되어 로또 번호를 생성하므로, 프로퍼티 대신 바로 생성자 내부에서 값을 초기화하는 방식으로 수정하는 것이 더 적절하겠네요!

덕분에 불필요한 프로퍼티 선언을 제거하고, 코드의 명확성과 간결성을 높일 수 있을 것 같습니다.

제안해주신대로 변경했습니다 👍

override val lottoNumbers: LottoNumbers = generateLottoNumbers()
}
}
24 changes: 0 additions & 24 deletions src/main/kotlin/lotto/domain/LottoTicketIssuer.kt

This file was deleted.

3 changes: 3 additions & 0 deletions src/main/kotlin/lotto/domain/LottoTickets.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package lotto.domain

data class LottoTickets(val lottoTickets: List<LottoTicket>)
6 changes: 3 additions & 3 deletions src/main/kotlin/lotto/domain/LottoWinnerNumbers.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ data class LottoWinnerNumbers(val lottoNumbers: LottoNumbers, val bonusNumber: L
require(!lottoNumbers.contains(bonusNumber)) { INVALID_WINNER_NUMBERS_MESSAGE }
}

fun resultLottoPayout(purchasedLottoTickets: PurchasedLottoTickets): PurchasedLottoResults {
fun resultLottoPayout(lottoTickets: LottoTickets): PurchasedLottoResults {
val rankCounts: Map<LottoWinnerRank, Int> =
purchasedLottoTickets.purchasedLottoTickets
lottoTickets.lottoTickets
.map { lottoTicket -> lottoTicket.checkLottoWinnerRank(this) }
.groupingBy { it }
.eachCount()

return PurchasedLottoResults(
purchasedCount = purchasedLottoTickets.purchasedCount,
purchasedCount = lottoTickets.lottoTickets.size,
firstRankCount = rankCounts[LottoWinnerRank.FIRST] ?: 0,
secondRankCount = rankCounts[LottoWinnerRank.SECOND] ?: 0,
thirdRankCount = rankCounts[LottoWinnerRank.THIRD] ?: 0,
Expand Down
6 changes: 3 additions & 3 deletions src/main/kotlin/lotto/domain/PurchasedLottoResults.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package lotto.domain

import lotto.domain.LottoTicketIssuer.DEFAULT_LOTTO_PRICE
import lotto.domain.PurchasedLottoTickets.Companion.INVALID_PURCHASED_COUNT_MESSAGE
import lotto.domain.PurchasedLottoTickets.Companion.PURCHASED_COUNT_MIN_VALUE
import lotto.domain.LottoPurchaseCalculator.DEFAULT_LOTTO_PRICE

data class PurchasedLottoResults(
val purchasedCount: Int,
Expand Down Expand Up @@ -38,6 +36,8 @@ data class PurchasedLottoResults(

companion object {
const val LOTTO_MATCH_COUNT_MIN_VALUE: Int = 0
const val PURCHASED_COUNT_MIN_VALUE: Int = 1
const val INVALID_PURCHASED_COUNT_MESSAGE: String = "구입한 로또 개수가 올바르지 않습니다"
const val INVALID_LOTTO_MATCH_COUNT_MESSAGE: String = "로또 당첨 번호 매치 결과는 0 이상 이어야합니다"
const val INVALID_PURCHASED_COUNT_LOTTO_MATCH_COUNT_MESSAGE: String = "당첨된 내역의 합이 구매한 개수보다 많을 수 없습니다"
}
Expand Down
18 changes: 0 additions & 18 deletions src/main/kotlin/lotto/domain/PurchasedLottoTickets.kt

This file was deleted.

40 changes: 40 additions & 0 deletions src/main/kotlin/lotto/view/ManualLottoView.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package lotto.view

import lotto.domain.LottoNumbers
import lotto.domain.LottoTicket.ManualLottoTicket
import lotto.domain.LottoTickets
import lotto.view.util.splitInputNumbersCommand

object ManualLottoView {
fun inputManualLottoCount(maxPurchaseLottoCount: Int): Int {
println("\n수동으로 구매할 로또 수를 입력해 주세요.")
val inputManualLottoCountCommand: String? = readlnOrNull()
requireNotNull(inputManualLottoCountCommand) { "입력된 수동 로또 개수가 없습니다." }

val inputManualLottoCount = inputManualLottoCountCommand.toIntOrNull()
requireNotNull(inputManualLottoCount) { "구입금액이 올바르게 입력되지 않았습니다." }
require(inputManualLottoCount >= 0) { "수동 로또 개수는 0개부터 입력 가능합니다." }
require(inputManualLottoCount <= maxPurchaseLottoCount) { "구입 가능한 수동 로또 개수를 초과했습니다." }

return inputManualLottoCount
}

fun repeatInputManualLottoNumbers(manualLottoCount: Int): LottoTickets {
println("\n수동으로 구매할 번호를 입력해 주세요.")

val lottoNumbersList = mutableListOf<LottoNumbers>()
repeat(manualLottoCount) { lottoNumbersList.add(inputManualLottoNumbers()) }
Copy link

Choose a reason for hiding this comment

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

이런식으로도 작성이 가능해보이네요! :)

Suggested change
val lottoNumbersList = mutableListOf<LottoNumbers>()
repeat(manualLottoCount) { lottoNumbersList.add(inputManualLottoNumbers()) }
val lottoNumbersList = List(manualLottoCount) { inputManualLottoNumbers() }

Copy link
Author

Choose a reason for hiding this comment

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

제안해 주신 대로 코드를 작성하면 한 줄로 더 간결하게 표현할 수 있겠네요!

map을 통해 ManualLottoTicket을 생성하는 부분이 바로 리스트 초기화와 결합되어 코드가 더 깔끔해진 것 같습니다.

가독성을 높일 수 있는 좋은 예시를 제안해 주셔서 감사합니다.


val lottoTickets = lottoNumbersList.map { ManualLottoTicket(it) }
Copy link

Choose a reason for hiding this comment

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

View에서 Tickets까지 만들어내는건 과한 책임인 것 같기도 한데요! List 혹은 List정도만 넘겨주면 어떨까요?

그러면서 중첩리스트를 반환하는게 괜찮은지? DTO를 만들어야하는지도 고민해보면 좋을 것 같아요!


return LottoTickets(lottoTickets)
}

private fun inputManualLottoNumbers(): LottoNumbers {
val inputManualNumbersCommand: String? = readlnOrNull()

requireNotNull(inputManualNumbersCommand) { "입력된 수동 번호가 없습니다." }

return splitInputNumbersCommand(inputManualNumbersCommand)
}
}
13 changes: 0 additions & 13 deletions src/main/kotlin/lotto/view/PurchaseLottoResultView.kt

This file was deleted.

15 changes: 15 additions & 0 deletions src/main/kotlin/lotto/view/PurchaseLottoView.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
package lotto.view

import lotto.domain.LottoTickets

object PurchaseLottoView {
fun inputPurchaseCost(): Int {
println("구입금액을 입력해 주세요.")
val inputCost: String? = readlnOrNull()
requireNotNull(inputCost) { "구입금액이 입력되지 않았습니다" }
requireNotNull(inputCost.toIntOrNull()) { "구입금액이 올바르게 입력되지 않았습니다" }

return inputCost.toInt()
}

fun displayPurchasedLottosView(
manualLottoTickets: LottoTickets,
autoLottoTickets: LottoTickets,
) {
val manualLottoCount = manualLottoTickets.lottoTickets.size
val autoLottoCount = autoLottoTickets.lottoTickets.size
println("\n수동으로 ${manualLottoCount}장, 자동으로 ${autoLottoCount}개를 구매했습니다.")

manualLottoTickets.lottoTickets.forEach { println(it.lottoNumbers.getNumbers()) }
autoLottoTickets.lottoTickets.forEach { println(it.lottoNumbers.getNumbers()) }
}
}
Loading