-
Notifications
You must be signed in to change notification settings - Fork 358
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] 로또(자동) #724
base: kyudong3
Are you sure you want to change the base?
[Step2] 로또(자동) #724
Changes from all commits
94bfcfb
db4b96d
6a39167
76a7130
03d2c30
23fd1fc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package lotto | ||
|
||
object InputView { | ||
|
||
fun requestPurchaseAmount(): Int { | ||
printMessage("구입금액을 입력해 주세요.") | ||
return readln().toInt() | ||
} | ||
|
||
fun requestLastWinnerNumbers(): List<Int> { | ||
printMessage("\n지난 주 당첨 번호를 입력해 주세요.") | ||
return readln().split(",").map { | ||
it.trim().toInt() | ||
} | ||
Comment on lines
+12
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 메서드를 연속해서 호출하는 경우에는 행 구분을 해주세요! https://kotlinlang.org/docs/coding-conventions.html#wrap-chained-calls There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. kotlin convention을 다시 한 번 제대로 읽어봐야겠어요 감사합니다! 🙏🏼 |
||
} | ||
|
||
private fun printMessage(message: String) { | ||
println(message) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package lotto | ||
|
||
data class Lottery( | ||
val numbers: List<Int> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 로또의 번호는 1~45까지 허용하는데요. 이를 벗어나지 않도록 방지해줄 수 있다면 더 좋지 않을까요?
|
||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package lotto | ||
|
||
data class LotteryResult( | ||
val prize: Int, | ||
val matchCount: Int, | ||
val message: String | ||
) |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,21 @@ | ||||||||||||||||||||
package lotto | ||||||||||||||||||||
|
||||||||||||||||||||
class LotteryShop { | ||||||||||||||||||||
|
||||||||||||||||||||
fun buy(money: Int): UserLottery { | ||||||||||||||||||||
val count = money / LOTTERY_PRICE | ||||||||||||||||||||
val lotteryTickets = mutableListOf<Lottery>() | ||||||||||||||||||||
repeat(count) { | ||||||||||||||||||||
lotteryTickets.add( | ||||||||||||||||||||
Lottery((MIN_LOTTERY_NUMBER..MAX_LOTTERY_NUMBER).shuffled().take(6).sorted()) | ||||||||||||||||||||
) | ||||||||||||||||||||
} | ||||||||||||||||||||
Comment on lines
+7
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 가변적인 아래와 같이 개선해보면 좋을것 같습니다.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 리턴할 때 UserLottery에 List 타입으로 선언해 추가해주었는데, buy 메소드 안에서도 가변적인 리스트보다 불변 리스트를 생성해 리턴하면 더 좋을 것 같네요!! 👍🏼 |
||||||||||||||||||||
return UserLottery(count, lotteryTickets) | ||||||||||||||||||||
} | ||||||||||||||||||||
|
||||||||||||||||||||
companion object { | ||||||||||||||||||||
private const val LOTTERY_PRICE = 1000 | ||||||||||||||||||||
private const val MIN_LOTTERY_NUMBER = 1 | ||||||||||||||||||||
private const val MAX_LOTTERY_NUMBER = 45 | ||||||||||||||||||||
} | ||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package lotto | ||
|
||
object LotteryStatistic { | ||
|
||
fun getWinStatistic( | ||
lotteryTickets: List<Lottery>, | ||
lastWinnerNumbers: List<Int> | ||
): Pair<List<LotteryResult>, Double> { | ||
val winResult = checkLotteryTickets(lotteryTickets, lastWinnerNumbers) | ||
|
||
val lotteryResults = mutableListOf<LotteryResult>() | ||
var sum = 0 | ||
winResult.forEach { (count, matchCount) -> | ||
val prize = WinnerPrize.getPrize(count).money | ||
val message = "${count}개 일치 (${prize}원) - ${matchCount}개" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 도메인 객체에서 view에 대한 책임까지 담당하고 있는것 같아보입니다. view에 대한 요구사항이 지금은 console에 띄우는 것 말고 없지만 다른 view가 추가로 들어오게 된다면 대처하기 어려울 것 같습니다. 따라서 view에 대해 어떻게 표현할지는 view에게 일임하는것이 좋아보입니다. domain 로직에서 view에 대한 구현상세 부분은 제거해주세요! |
||
lotteryResults.add(LotteryResult(prize, matchCount, message)) | ||
sum += (prize * matchCount) | ||
} | ||
|
||
return lotteryResults.toList() to sum.toDouble() | ||
Comment on lines
+5
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
그러면 전체적인 코드가 조금 더 간결해 질 수 있을것 같습니다. |
||
} | ||
|
||
private fun checkLotteryTickets( | ||
lotteryTickets: List<Lottery>, | ||
lastWinnerNumbers: List<Int> | ||
): List<Pair<Int, Int>> = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
lotteryTickets.map { lottery -> | ||
lottery.numbers.intersect( | ||
lastWinnerNumbers.sorted().toSet() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 정렬할 필요가 있을까요?? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 다시 생각해보니 sort할 필요는 없는 것 같네요..! 🙏🏼 |
||
).count() | ||
}.filter { it >= 3 } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 3개가 넘게 일치하는지를 이곳에서 판별하지 않고
|
||
.groupingBy { it } | ||
.eachCount() | ||
.toList() | ||
.sortedBy { it.first } | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package lotto | ||
|
||
fun main() { | ||
val lotteryShop = LotteryShop() | ||
val money = InputView.requestPurchaseAmount() | ||
val userLotteryInfo = lotteryShop.buy(money) | ||
|
||
ResultView.printLotteryCount(userLotteryInfo.lotteryCount) | ||
ResultView.printAllLotteries(userLotteryInfo.lotteryTickets) | ||
|
||
val lastWinnerNumbers = InputView.requestLastWinnerNumbers() | ||
val lotteryResults = LotteryStatistic.getWinStatistic(userLotteryInfo.lotteryTickets, lastWinnerNumbers) | ||
|
||
ResultView.printWinStatistic(lotteryResults, money) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package lotto | ||
|
||
object ResultView { | ||
|
||
fun printLotteryCount(size: Int) { | ||
println("${size}개를 구매했습니다.") | ||
} | ||
|
||
fun printAllLotteries(lotteryTickets: List<Lottery>) { | ||
lotteryTickets.forEach { lottery -> | ||
println(lottery.numbers) | ||
} | ||
} | ||
|
||
fun printWinStatistic( | ||
lotteryResults: Pair<List<LotteryResult>, Double>, | ||
money: Int | ||
) { | ||
println("\n당첨 통계\n-------------------") | ||
lotteryResults.first.forEach { lotteryResult -> | ||
println(lotteryResult.message) | ||
} | ||
println(String.format("총 수익률은 %.2f 입니다", lotteryResults.second / money)) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package lotto | ||
|
||
data class UserLottery( | ||
val lotteryCount: Int, | ||
val lotteryTickets: List<Lottery> | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package lotto | ||
|
||
enum class WinnerPrize(val money: Int) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1등에 여러번 당첨되면 |
||
|
||
FIRST(2_000_000_000), | ||
SECOND(1_500_000), | ||
THIRD(50_000), | ||
LAST(5_000); | ||
|
||
companion object { | ||
fun getPrize(sameCount: Int): WinnerPrize = when (sameCount) { | ||
3 -> LAST | ||
4 -> THIRD | ||
5 -> SECOND | ||
else -> FIRST | ||
Comment on lines
+12
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package lotto | ||
|
||
import io.kotest.core.spec.style.StringSpec | ||
import io.kotest.inspectors.forAll | ||
import io.kotest.matchers.shouldBe | ||
|
||
class LotteryShopKoTest : StringSpec({ | ||
|
||
"구매한 금액에 해당하는 로또 갯수 반환" { | ||
val lotteryShop = LotteryShop() | ||
val actualInput = 14_000 | ||
lotteryShop.buy(actualInput).lotteryCount shouldBe 14 | ||
} | ||
|
||
"일치하는 로또 갯수에 의한 당첨 금액" { | ||
val first = WinnerPrize.getPrize(6) | ||
val second = WinnerPrize.getPrize(5) | ||
val third = WinnerPrize.getPrize(4) | ||
val last = WinnerPrize.getPrize(3) | ||
|
||
first.money shouldBe 2_000_000_000 | ||
second.money shouldBe 1_500_000 | ||
third.money shouldBe 50_000 | ||
last.money shouldBe 5_000 | ||
} | ||
|
||
"구매한 로또들과 지난 주 당첨 번호가 일치하는지 확인" { | ||
val lastWinnerNumbers = listOf(1, 2, 3, 4, 5, 6) | ||
val lotteryTickets = listOf( | ||
Lottery(listOf(1, 2, 3, 4, 39, 43)), | ||
Lottery(listOf(9, 11, 21, 27, 28, 32)), | ||
Lottery(listOf(4, 5, 14, 17, 31, 35)), | ||
Lottery(listOf(11, 13, 17, 22, 25, 34)), | ||
Lottery(listOf(1, 3, 5, 21, 41, 42)), | ||
Lottery(listOf(6, 7, 17, 19, 32, 35)), | ||
Lottery(listOf(2, 12, 19, 34, 35, 37)), | ||
Lottery(listOf(1, 3, 5, 6, 39, 44)), | ||
Lottery(listOf(2, 5, 8, 10, 13, 23)), | ||
Lottery(listOf(7, 29, 30, 31, 34, 36)) | ||
) | ||
|
||
val lotteryResults = LotteryStatistic.getWinStatistic(lotteryTickets, lastWinnerNumbers).first | ||
|
||
lotteryResults.forEach { | ||
when (it.prize) { | ||
3 -> it.matchCount shouldBe 1 | ||
4 -> it.matchCount shouldBe 2 | ||
5 -> it.matchCount shouldBe 0 | ||
6 -> it.matchCount shouldBe 0 | ||
} | ||
Comment on lines
+28
to
+50
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 검증에 불필요한 테스트 데이터는 제거해서 테스트를 간소화해주시는것이 가독성을 높이는 방법이 될 수 있습니다. 이 테스트에서 구매한 당첨번호가 일치하는지를 확인하고 싶으시다면 상금의 일치하는 갯수에 맞게 |
||
} | ||
} | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package lotto | ||
|
||
import org.assertj.core.api.Assertions.assertThat | ||
import org.junit.jupiter.api.Test | ||
|
||
class LotteryShopTest { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Junit으로 동일한 테스트를 한번 더 작성해주셨네요! Kotest, Junit 둘 중 하나만 사용해주셔도 좋을것 같습니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 네네! Junit과 kotest 모두 익숙하지 않아 둘 다 사용해보고 있는데 다음부터는 kotest만 사용하려고 합니다! 🙏🏼 |
||
|
||
@Test | ||
fun `구매한 금액에 해당하는 로또 갯수 반환`() { | ||
val lotteryShop = LotteryShop() | ||
val actualInput = 14_000 | ||
val userLottery = lotteryShop.buy(actualInput) | ||
assertThat(userLottery.lotteryCount).isEqualTo(14) | ||
} | ||
|
||
@Test | ||
fun `일치하는 로또 갯수에 의한 당첨 금액`() { | ||
val first = WinnerPrize.getPrize(6) | ||
val second = WinnerPrize.getPrize(5) | ||
val third = WinnerPrize.getPrize(4) | ||
val last = WinnerPrize.getPrize(3) | ||
|
||
assertThat(first.money).isEqualTo(2_000_000_000) | ||
assertThat(second.money).isEqualTo(1_500_000) | ||
assertThat(third.money).isEqualTo(50_000) | ||
assertThat(last.money).isEqualTo(5_000) | ||
} | ||
|
||
@Test | ||
fun `구매한 로또들과 지난 주 당첨 번호가 일치하는지 확인`() { | ||
val lastWinnerNumbers = listOf(1, 2, 3, 4, 5, 6) | ||
val lotteryTickets = listOf( | ||
Lottery(listOf(1, 2, 3, 4, 39, 43)), | ||
Lottery(listOf(9, 11, 21, 27, 28, 32)), | ||
Lottery(listOf(4, 5, 14, 17, 31, 35)), | ||
Lottery(listOf(11, 13, 17, 22, 25, 34)), | ||
Lottery(listOf(1, 3, 5, 21, 41, 42)), | ||
Lottery(listOf(6, 7, 17, 19, 32, 35)), | ||
Lottery(listOf(2, 12, 19, 34, 35, 37)), | ||
Lottery(listOf(1, 3, 5, 6, 39, 44)), | ||
Lottery(listOf(2, 5, 8, 10, 13, 23)), | ||
Lottery(listOf(7, 29, 30, 31, 34, 36)) | ||
) | ||
|
||
val lotteryResults = LotteryStatistic.getWinStatistic(lotteryTickets, lastWinnerNumbers).first | ||
|
||
lotteryResults.forEach { | ||
when (it.prize) { | ||
3 -> assertThat(it.matchCount).isEqualTo(1) | ||
4 -> assertThat(it.matchCount).isEqualTo(2) | ||
5 -> assertThat(it.matchCount).isEqualTo(0) | ||
6 -> assertThat(it.matchCount).isEqualTo(0) | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
패키지를 구조를 변경하여 domain 과 view 를 분리해주세요.