diff --git a/src/main/kotlin/lotto/LottoSimulator.kt b/src/main/kotlin/lotto/LottoSimulator.kt index 599e8f5d6e..b342f6f417 100644 --- a/src/main/kotlin/lotto/LottoSimulator.kt +++ b/src/main/kotlin/lotto/LottoSimulator.kt @@ -3,8 +3,12 @@ package lotto import lotto.domain.LottoPurchaseOrder import lotto.domain.LottoResult import lotto.domain.LottoTicket -import lotto.provider.ticket.AutoTicketProvider -import lotto.provider.ticket.LottoTicketsProvider +import lotto.domain.LottoTickets +import lotto.domain.RankResult +import lotto.generator.ActualLottoShop +import lotto.generator.LottoShop +import lotto.generator.ticket.AutoTicketGenerator +import lotto.generator.ticket.ManualTicketGenerator import lotto.view.InputView import lotto.view.ResultView import lotto.view.UserInputView @@ -13,16 +17,16 @@ class LottoSimulator( private val inputView: InputView, private val resultView: ResultView, ) { - fun simulate(lottoTicketsProvider: LottoTicketsProvider): LottoResult { + fun simulate(lottoShop: LottoShop): LottoResult { val purchaseOrder = LottoPurchaseOrder( budget = inputView.getBudget(), ticketPrice = LottoTicket.PRICE, ) - val lottoTickets = lottoTicketsProvider.provide(purchaseOrder.ticketCount) - inputView.printPurchasedLotto(lottoTickets) + val lottoTickets = generateLottoTickets(lottoShop, purchaseOrder.ticketCount) val winningNumber = inputView.getWinningNumber() + val lottoResult = lottoTickets.getRankResult(winningNumber) val result = LottoResult( @@ -31,9 +35,27 @@ class LottoSimulator( remainder = purchaseOrder.remainder ) + printLottoResult(lottoResult, result) + + return result + } + + private fun printLottoResult(lottoResult: RankResult, result: LottoResult) { resultView.printRankResults(lottoResult) resultView.printResult(result) - return result + } + + private fun generateLottoTickets(lottoShop: LottoShop, ticketCount: Int): LottoTickets { + val manualLottoCount = inputView.getManualLottoCount() + + val manualTickets = if (manualLottoCount != 0) { + lottoShop.provideManualTickets(inputView.getManualNumbers(manualLottoCount)) + } else LottoTickets(listOf()) + + val autoTickets = lottoShop.provideAutoTickets(ticketCount, manualLottoCount) + inputView.printPurchasedLotto(autoLottoTickets = autoTickets, manualLottoTickets = manualTickets) + + return LottoTickets(manualTickets.lottoTicketList + autoTickets.lottoTicketList) } } @@ -41,5 +63,10 @@ fun main() { LottoSimulator( UserInputView(), ResultView() - ).simulate(lottoTicketsProvider = AutoTicketProvider) + ).simulate( + lottoShop = ActualLottoShop( + autoTicketGenerator = AutoTicketGenerator, + manualTicketGenerator = ManualTicketGenerator, + ) + ) } diff --git a/src/main/kotlin/lotto/domain/ManualTicketProvideStrategy.kt b/src/main/kotlin/lotto/domain/ManualTicketProvideStrategy.kt deleted file mode 100644 index e38590939f..0000000000 --- a/src/main/kotlin/lotto/domain/ManualTicketProvideStrategy.kt +++ /dev/null @@ -1,7 +0,0 @@ -package lotto.domain - -import lotto.provider.ticket.TicketProvideStrategy - -class ManualTicketProvideStrategy(private val lottoTickets: LottoTickets) : TicketProvideStrategy { - override fun provide(ticketCount: Int): LottoTickets = lottoTickets -} diff --git a/src/main/kotlin/lotto/generator/ActualLottoShop.kt b/src/main/kotlin/lotto/generator/ActualLottoShop.kt new file mode 100644 index 0000000000..48a611deeb --- /dev/null +++ b/src/main/kotlin/lotto/generator/ActualLottoShop.kt @@ -0,0 +1,14 @@ +package lotto.generator + +import lotto.domain.LottoTickets +import lotto.generator.ticket.AutoTicketGenerator +import lotto.generator.ticket.ManualTicketGenerator + +class ActualLottoShop( + private val autoTicketGenerator: AutoTicketGenerator, + private val manualTicketGenerator: ManualTicketGenerator, +) : LottoShop { + override fun provideAutoTickets(ticketCount: Int, preGeneratedTicketCount: Int): LottoTickets = autoTicketGenerator.create(ticketCount - preGeneratedTicketCount) + override fun provideManualTickets(manualNumbersList: List>): LottoTickets = + manualTicketGenerator.create(manualNumbersList) +} diff --git a/src/main/kotlin/lotto/generator/LottoShop.kt b/src/main/kotlin/lotto/generator/LottoShop.kt new file mode 100644 index 0000000000..5bcb2e5cf4 --- /dev/null +++ b/src/main/kotlin/lotto/generator/LottoShop.kt @@ -0,0 +1,8 @@ +package lotto.generator + +import lotto.domain.LottoTickets + +interface LottoShop { + fun provideAutoTickets(ticketCount: Int, preGeneratedTicketCount: Int): LottoTickets + fun provideManualTickets(manualNumbersList: List>): LottoTickets +} diff --git a/src/main/kotlin/lotto/domain/AutoTicketProvideStrategy.kt b/src/main/kotlin/lotto/generator/ticket/AutoTicketGenerator.kt similarity index 65% rename from src/main/kotlin/lotto/domain/AutoTicketProvideStrategy.kt rename to src/main/kotlin/lotto/generator/ticket/AutoTicketGenerator.kt index 404bb8fd97..9871c49e95 100644 --- a/src/main/kotlin/lotto/domain/AutoTicketProvideStrategy.kt +++ b/src/main/kotlin/lotto/generator/ticket/AutoTicketGenerator.kt @@ -1,11 +1,14 @@ -package lotto.domain +package lotto.generator.ticket -import lotto.provider.ticket.TicketProvideStrategy +import lotto.domain.LottoNumber +import lotto.domain.LottoTicket +import lotto.domain.LottoTickets -object AutoTicketProvideStrategy : TicketProvideStrategy { +object AutoTicketGenerator { private val preGeneratedLottoNumbers = (LottoNumber.validNumberRange) .map { LottoNumber(it) } - override fun provide(ticketCount: Int): LottoTickets { + + fun create(ticketCount: Int): LottoTickets { val tickets = List(ticketCount) { LottoTicket( preGeneratedLottoNumbers diff --git a/src/main/kotlin/lotto/generator/ticket/ManualTicketGenerator.kt b/src/main/kotlin/lotto/generator/ticket/ManualTicketGenerator.kt new file mode 100644 index 0000000000..c3eede0c89 --- /dev/null +++ b/src/main/kotlin/lotto/generator/ticket/ManualTicketGenerator.kt @@ -0,0 +1,15 @@ +package lotto.generator.ticket + +import lotto.domain.LottoNumber +import lotto.domain.LottoTicket +import lotto.domain.LottoTickets + +object ManualTicketGenerator { + fun create(manualNumbersList: List>): LottoTickets { + return LottoTickets( + manualNumbersList.map { list -> + LottoTicket(list.map { LottoNumber(it) }) + } + ) + } +} diff --git a/src/main/kotlin/lotto/provider/ticket/AutoTicketProvider.kt b/src/main/kotlin/lotto/provider/ticket/AutoTicketProvider.kt deleted file mode 100644 index 0189046e12..0000000000 --- a/src/main/kotlin/lotto/provider/ticket/AutoTicketProvider.kt +++ /dev/null @@ -1,8 +0,0 @@ -package lotto.provider.ticket - -import lotto.domain.AutoTicketProvideStrategy -import lotto.domain.LottoTickets - -object AutoTicketProvider : LottoTicketsProvider(AutoTicketProvideStrategy) { - override fun provide(ticketCount: Int): LottoTickets = ticketProvideStrategy.provide(ticketCount) -} diff --git a/src/main/kotlin/lotto/provider/ticket/LottoTicketsProvider.kt b/src/main/kotlin/lotto/provider/ticket/LottoTicketsProvider.kt deleted file mode 100644 index dc92e8178a..0000000000 --- a/src/main/kotlin/lotto/provider/ticket/LottoTicketsProvider.kt +++ /dev/null @@ -1,11 +0,0 @@ -package lotto.provider.ticket - -import lotto.domain.LottoTickets - -abstract class LottoTicketsProvider(protected val ticketProvideStrategy: TicketProvideStrategy) { - abstract fun provide(ticketCount: Int): LottoTickets -} - -interface TicketProvideStrategy { - fun provide(ticketCount: Int): LottoTickets -} diff --git a/src/main/kotlin/lotto/view/InputView.kt b/src/main/kotlin/lotto/view/InputView.kt index 0ddd88badc..14034c611f 100644 --- a/src/main/kotlin/lotto/view/InputView.kt +++ b/src/main/kotlin/lotto/view/InputView.kt @@ -8,5 +8,9 @@ interface InputView { fun getWinningNumber(): WinningNumber - fun printPurchasedLotto(lottoTickets: LottoTickets) + fun printPurchasedLotto(autoLottoTickets: LottoTickets, manualLottoTickets: LottoTickets) + + fun getManualLottoCount(): Int + + fun getManualNumbers(manualLottoCount: Int): List> } diff --git a/src/main/kotlin/lotto/view/UserInputView.kt b/src/main/kotlin/lotto/view/UserInputView.kt index 682cb2777e..892101418c 100644 --- a/src/main/kotlin/lotto/view/UserInputView.kt +++ b/src/main/kotlin/lotto/view/UserInputView.kt @@ -24,14 +24,35 @@ class UserInputView : InputView { ) } - override fun printPurchasedLotto(lottoTickets: LottoTickets) { - lottoTickets.lottoTicketList.forEach { ticket -> + override fun printPurchasedLotto(autoLottoTickets: LottoTickets, manualLottoTickets: LottoTickets) { + println("수동으로 ${manualLottoTickets.lottoTicketList.size}, 자동으로 ${autoLottoTickets.lottoTicketList.size} 개를 구매했습니다.") + manualLottoTickets.print() + autoLottoTickets.print() + } + + override fun getManualLottoCount(): Int { + println("수동으로 구매할 로또 수를 입력해 주세요.") + return readln().trim().toInt() + } + + override fun getManualNumbers(manualLottoCount: Int): List> { + println("수동으로 구매할 번호를 입력해 주세요.") + val lottoTicketNumbers = mutableListOf>() + + repeat(manualLottoCount) { + val lottoTicket = readln().trim().split(",").map { it.toInt() } + lottoTicketNumbers.add(lottoTicket) + } + return lottoTicketNumbers + } + + private fun LottoTickets.print() { + lottoTicketList.forEach { ticket -> println( ticket.lottoNumberList.map { number -> number.value } ) } - println("${lottoTickets.lottoTicketList.size} 개를 구매했습니다.") } } diff --git a/src/test/kotlin/lotto/LottoAutoTest.kt b/src/test/kotlin/lotto/LottoAutoTest.kt index 9e930a20dc..125aa82f99 100644 --- a/src/test/kotlin/lotto/LottoAutoTest.kt +++ b/src/test/kotlin/lotto/LottoAutoTest.kt @@ -4,11 +4,10 @@ import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import lotto.domain.LottoNumber import lotto.domain.LottoTicket -import lotto.domain.LottoTickets -import lotto.domain.ManualTicketProvideStrategy import lotto.domain.Rank import lotto.domain.WinningNumber -import lotto.provider.ticket.MockTicketProvider +import lotto.generator.MockLottoShop +import lotto.generator.ticket.ManualTicketGenerator import lotto.view.MockInputView import lotto.view.ResultView @@ -17,22 +16,17 @@ class LottoAutoTest : StringSpec({ "winning statistics should calculate correct profit" { LottoSimulator( inputView = MockInputView( - budget = 5000, + budget = 1000, winningNumber = WinningNumber( LottoTicket(listOf(1, 2, 3, 4, 5, 6).map { LottoNumber(it) }), bonusNumber = LottoNumber(19) ), + manualNumbersList = listOf(listOf(1, 2, 3, 4, 5, 6)) ), resultView = ResultView(), ).simulate( - lottoTicketsProvider = MockTicketProvider( - ManualTicketProvideStrategy( - LottoTickets( - listOf( - LottoTicket(listOf(1, 2, 3, 4, 5, 6).map { LottoNumber(it) }) - ) - ) - ), + lottoShop = MockLottoShop( + manualTicketGenerator = ManualTicketGenerator ) ).totalPrize shouldBe Rank.FirstPlace.prize } @@ -40,45 +34,35 @@ class LottoAutoTest : StringSpec({ "winning statistics should show correct ROI" { LottoSimulator( inputView = MockInputView( - budget = 5000, + budget = 1000, winningNumber = WinningNumber( LottoTicket(listOf(1, 2, 3, 4, 5, 6).map { LottoNumber(it) }), bonusNumber = LottoNumber(19) ), + manualNumbersList = listOf(listOf(1, 2, 3, 4, 5, 6)) ), resultView = ResultView(), ).simulate( - lottoTicketsProvider = MockTicketProvider( - ManualTicketProvideStrategy( - LottoTickets( - listOf( - LottoTicket(listOf(1, 2, 3, 4, 5, 6).map { LottoNumber(it) }) - ) - ) - ) + lottoShop = MockLottoShop( + manualTicketGenerator = ManualTicketGenerator ), - ).profitRate.shouldBe(400_000) + ).profitRate.shouldBe(2_000_000) } "second place result should be correct" { LottoSimulator( inputView = MockInputView( - budget = 5000, + budget = 1000, winningNumber = WinningNumber( LottoTicket(listOf(1, 2, 3, 4, 5, 9).map { LottoNumber(it) }), bonusNumber = LottoNumber(19) ), + manualNumbersList = listOf(listOf(1, 2, 3, 4, 5, 19)) ), resultView = ResultView(), ).simulate( - lottoTicketsProvider = MockTicketProvider( - ManualTicketProvideStrategy( - LottoTickets( - listOf( - LottoTicket(listOf(1, 2, 3, 4, 5, 19).map { LottoNumber(it) }) - ) - ) - ) + lottoShop = MockLottoShop( + manualTicketGenerator = ManualTicketGenerator ), ).totalPrize shouldBe Rank.SecondPlace.prize } diff --git a/src/test/kotlin/lotto/generator/MockLottoShop.kt b/src/test/kotlin/lotto/generator/MockLottoShop.kt new file mode 100644 index 0000000000..89e2efe263 --- /dev/null +++ b/src/test/kotlin/lotto/generator/MockLottoShop.kt @@ -0,0 +1,10 @@ +package lotto.generator + +import lotto.domain.LottoTickets +import lotto.generator.ticket.ManualTicketGenerator + +class MockLottoShop(private val manualTicketGenerator: ManualTicketGenerator) : LottoShop { + override fun provideAutoTickets(ticketCount: Int, preGeneratedTicketCount: Int): LottoTickets = LottoTickets(listOf()) + override fun provideManualTickets(manualNumbersList: List>): LottoTickets = + manualTicketGenerator.create(manualNumbersList) +} diff --git a/src/test/kotlin/lotto/generator/ticket/AutoTicketGeneratorTest.kt b/src/test/kotlin/lotto/generator/ticket/AutoTicketGeneratorTest.kt new file mode 100644 index 0000000000..a1f7227aca --- /dev/null +++ b/src/test/kotlin/lotto/generator/ticket/AutoTicketGeneratorTest.kt @@ -0,0 +1,14 @@ +package lotto.generator.ticket + +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe + +class AutoTicketGeneratorTest : BehaviorSpec({ + given("auto ticket generator") { + `when`("creates lotto Tickets") { + then("should provide correct ticket count") { + AutoTicketGenerator.create(3).lottoTicketList.size shouldBe 3 + } + } + } +}) diff --git a/src/test/kotlin/lotto/generator/ticket/ManualTicketGeneratorTest.kt b/src/test/kotlin/lotto/generator/ticket/ManualTicketGeneratorTest.kt new file mode 100644 index 0000000000..5ed47065a9 --- /dev/null +++ b/src/test/kotlin/lotto/generator/ticket/ManualTicketGeneratorTest.kt @@ -0,0 +1,30 @@ +package lotto.generator.ticket + +import io.kotest.core.spec.style.BehaviorSpec +import io.kotest.matchers.shouldBe +import lotto.domain.LottoNumber +import lotto.domain.LottoTicket + +class ManualTicketGeneratorTest : BehaviorSpec({ + given("manual ticket generator") { + `when`("creates lotto Tickets") { + then("should provide correct tickets") { + val ticketBlueprint1 = listOf(1, 2, 3, 4, 5, 6) + val ticketBlueprint2 = listOf(3, 4, 5, 6, 7, 8) + val ticketBlueprint3 = listOf(5, 6, 7, 8, 9, 13) + + val lottoTickets = ManualTicketGenerator.create( + listOf( + ticketBlueprint1, + ticketBlueprint2, + ticketBlueprint3, + ) + ) + lottoTickets.lottoTicketList.size shouldBe 3 + lottoTickets.lottoTicketList[0] shouldBe LottoTicket(ticketBlueprint1.map { LottoNumber(it) }) + lottoTickets.lottoTicketList[1] shouldBe LottoTicket(ticketBlueprint2.map { LottoNumber(it) }) + lottoTickets.lottoTicketList[2] shouldBe LottoTicket(ticketBlueprint3.map { LottoNumber(it) }) + } + } + } +}) diff --git a/src/test/kotlin/lotto/provider/ticket/MockTicketProvider.kt b/src/test/kotlin/lotto/provider/ticket/MockTicketProvider.kt deleted file mode 100644 index 8b3b635e7a..0000000000 --- a/src/test/kotlin/lotto/provider/ticket/MockTicketProvider.kt +++ /dev/null @@ -1,8 +0,0 @@ -package lotto.provider.ticket - -import lotto.domain.LottoTickets -import lotto.domain.ManualTicketProvideStrategy - -class MockTicketProvider(ticketProvideStrategy: ManualTicketProvideStrategy) : LottoTicketsProvider(ticketProvideStrategy) { - override fun provide(ticketCount: Int): LottoTickets = ticketProvideStrategy.provide(ticketCount) -} diff --git a/src/test/kotlin/lotto/view/MockInputView.kt b/src/test/kotlin/lotto/view/MockInputView.kt index 51749b9be5..48dd281e8c 100644 --- a/src/test/kotlin/lotto/view/MockInputView.kt +++ b/src/test/kotlin/lotto/view/MockInputView.kt @@ -6,10 +6,15 @@ import lotto.domain.WinningNumber class MockInputView( private val budget: Int, private val winningNumber: WinningNumber, + private val manualNumbersList: List>, ) : InputView { override fun getBudget(): Int = budget override fun getWinningNumber(): WinningNumber = winningNumber - override fun printPurchasedLotto(lottoTickets: LottoTickets) = Unit + override fun printPurchasedLotto(autoLottoTickets: LottoTickets, manualLottoTickets: LottoTickets) = Unit + + override fun getManualLottoCount(): Int = manualNumbersList.size + + override fun getManualNumbers(manualLottoCount: Int): List> = manualNumbersList }