-
Notifications
You must be signed in to change notification settings - Fork 323
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] 로또 자동 #797
base: choihwan2
Are you sure you want to change the base?
[Step2] 로또 자동 #797
Changes from all commits
7db83e6
bcfc4f5
070e274
3695ccc
1a854bf
5c88c78
786c4e6
10a286d
8504991
a316730
092ac13
9b2f468
e4875eb
656bbb1
ddfa00c
7dc228b
a32e800
5d7e88a
cec863a
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,40 @@ | ||
package lottery.controller | ||
|
||
import lottery.domain.Lotteries | ||
import lottery.domain.Lottery | ||
import lottery.domain.LotteryNumber | ||
import lottery.domain.LotteryPrize | ||
import lottery.domain.LotteryRank | ||
import lottery.domain.WinningLottery | ||
import lottery.view.LotteryGameView | ||
|
||
class LotteryGame { | ||
private lateinit var winningLottery: WinningLottery | ||
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 val lotteryRank = LotteryRank() | ||
fun purchaseAutoLotteries(purchasePrice: Int): Lotteries { | ||
return Lotteries.makeAutoLotteries(purchasePrice / Lottery.LOTTERY_PRICE) | ||
} | ||
|
||
fun start() { | ||
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.
|
||
LotteryGameView.printPurchaseMoneyView() | ||
val money = readln().toInt() | ||
Comment on lines
+19
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.
|
||
val purchaseAutoLotteries = purchaseAutoLotteries(money) | ||
LotteryGameView.printPurchaseLotteryView(purchaseAutoLotteries.lotteries.size) | ||
LotteryGameView.printLotteriesNumber(purchaseAutoLotteries) | ||
LotteryGameView.printWinnerLotteryNumber() | ||
val numbers = readln().replace("\\s".toRegex(), "").split(",") | ||
Comment on lines
+24
to
+25
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. 이 부분도 |
||
winningLottery = WinningLottery(numbers.map { LotteryNumber.get(it.toInt()) }.toSet()) | ||
|
||
purchaseAutoLotteries.lotteries.forEach { | ||
val correctCount = it.checkCorrectCount(winningLottery.winningNumbers) | ||
lotteryRank.plusRank(LotteryPrize.get(correctCount) ?: LotteryPrize.NONE) | ||
} | ||
LotteryGameView.printLotteryRankView(lotteryRank) | ||
LotteryGameView.printProfitView(lotteryRank.calculateProfit(money)) | ||
} | ||
} | ||
|
||
fun main() { | ||
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.
|
||
val game = LotteryGame() | ||
game.start() | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,15 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
package lottery.domain | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
class Lotteries { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
val lotteries = mutableListOf<Lottery>() | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
companion object { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
fun makeAutoLotteries(number: Int): Lotteries { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
val lotteries = Lotteries() | ||||||||||||||||||||||||||||||||||||||||||||||||||||
for (i in 0 until number) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
lotteries.lotteries.add(Lottery.makeAutoLottery()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
return lotteries | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+3
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. 객체를 생성할 때 가능하면 완벽한 상태로 생성하는게 좋습니다.
Suggested change
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package lottery.domain | ||
|
||
class Lottery(numbers: Set<LotteryNumber>) { | ||
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.
|
||
val lotteryNumbers: Set<LotteryNumber> | ||
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. 생성자에 |
||
|
||
init { | ||
require(!hasDuplicatedLotteryNumbers(numbers)) { "로또 번호에 중복되는 숫자가 있습니다." } | ||
lotteryNumbers = numbers | ||
} | ||
|
||
private fun hasDuplicatedLotteryNumbers(numbers: Set<LotteryNumber>): Boolean { | ||
return numbers.size != LOTTERY_NUMBER_SIZE | ||
} | ||
|
||
fun checkCorrectCount(numbers: Set<LotteryNumber>): Int { | ||
return numbers.count { it in lotteryNumbers } | ||
} | ||
|
||
companion object { | ||
private val BASE_NUMBERS = (LotteryNumber.MIN_LOTTERY_NUMBER..LotteryNumber.MAX_LOTTERY_NUMBER).toSet() | ||
const val LOTTERY_NUMBER_SIZE = 6 | ||
const val LOTTERY_PRICE = 1000 | ||
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. 가격에 대한 정책은 게임에 더 가까울거 같아요! |
||
fun makeAutoLottery(): Lottery { | ||
return Lottery( | ||
BASE_NUMBERS.shuffled().take(LOTTERY_NUMBER_SIZE).sorted().map { LotteryNumber.get(it) } | ||
.toSet() | ||
) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package lottery.domain | ||
|
||
@JvmInline | ||
value class LotteryNumber private constructor( | ||
private val number: Int, | ||
) { | ||
init { | ||
require(number >= MIN_LOTTERY_NUMBER) { "로또 번호는 1이상여야 합니다." } | ||
require(number <= MAX_LOTTERY_NUMBER) { "로또 번호는 45이하이여야 합니다." } | ||
} | ||
|
||
companion object { | ||
fun get(number: Int) = LotteryNumber(number) | ||
|
||
const val MAX_LOTTERY_NUMBER = 45 | ||
const val MIN_LOTTERY_NUMBER = 1 | ||
} | ||
|
||
override fun toString(): String { | ||
return "$number" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package lottery.domain | ||
|
||
enum class LotteryPrize(val correctCount: Int, val rewardMoney: Int) { | ||
NONE(0, 0), | ||
FORTH(3, 5_000), | ||
THIRD(4, 50_000), | ||
SECOND(5, 1_500_000), | ||
FIRST(6, 2_000_000_000), ; | ||
|
||
companion object { | ||
fun get(correctCount: Int): LotteryPrize? { | ||
return LotteryPrize.values().find { it.correctCount == correctCount } | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package lottery.domain | ||
|
||
class LotteryRank { | ||
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. 그러면 팩터리메서드나 생성자를 통해 |
||
val lotteriesRank = LotteryPrize.values().associateWith { RANK_DEFAULT_VALUE }.toMutableMap() | ||
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. 이름에서 타입을 알 수 없으면 타입을 명시해볼까요? |
||
|
||
fun plusRank(rank: LotteryPrize) { | ||
lotteriesRank[rank] = lotteriesRank.getOrDefault(rank, 0) + 1 | ||
} | ||
|
||
fun calculateProfit(money: Int): Double { | ||
val total = lotteriesRank.map { (prize, count) -> | ||
prize.rewardMoney * count | ||
}.sumOf { it }.toDouble() | ||
return total / money | ||
} | ||
|
||
companion object { | ||
const val RANK_DEFAULT_VALUE = 0 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package lottery.domain | ||
|
||
class WinningLottery(numbers: Set<LotteryNumber>) { | ||
val winningNumbers: Set<LotteryNumber> | ||
Comment on lines
+3
to
+4
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. 이것도 생성자에 |
||
|
||
init { | ||
require(!hasDuplicatedLotteryNumbers(numbers)) { "로또 번호에 중복되는 숫자가 있습니다." } | ||
winningNumbers = numbers | ||
} | ||
|
||
private fun hasDuplicatedLotteryNumbers(numbers: Set<LotteryNumber>): Boolean { | ||
return numbers.size != Lottery.LOTTERY_NUMBER_SIZE | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package lottery.view | ||
|
||
import lottery.domain.Lotteries | ||
import lottery.domain.LotteryPrize | ||
import lottery.domain.LotteryRank | ||
|
||
object LotteryGameView { | ||
|
||
fun printPurchaseMoneyView() { | ||
println("구입 금액을 입력해 주세요.") | ||
} | ||
|
||
fun printPurchaseLotteryView(number: Int) { | ||
println("${number}개를 구매했습니다.") | ||
} | ||
|
||
fun printLotteriesNumber(lotteries: Lotteries) { | ||
lotteries.lotteries.forEach { | ||
println(it.lotteryNumbers) | ||
} | ||
println() | ||
} | ||
|
||
fun printWinnerLotteryNumber() { | ||
println("지난 주 당첨 번호를 입력해 주세요.") | ||
} | ||
|
||
fun printLotteryRankView(lotteryRank: LotteryRank) { | ||
println("당첨 통계") | ||
println("---------") | ||
lotteryRank.lotteriesRank.filter { it.key != LotteryPrize.NONE }.forEach { (prize, count) -> | ||
println("${prize.correctCount}개 일치 (${prize.rewardMoney}원)- ${count}개") | ||
} | ||
} | ||
|
||
fun printProfitView(profit: Double) { | ||
println("총 수익률은" + String.format("%.2f", profit) + " 입니다.") | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package lottery.controller | ||
|
||
import io.kotest.core.spec.style.StringSpec | ||
import io.kotest.matchers.shouldBe | ||
|
||
class LotteryGameTest : StringSpec({ | ||
"로또 구입 금액을 입력하면 구입 금액에 해당하는 로또를 발급해야 한다." { | ||
val lotteryGame = LotteryGame() | ||
val purchaseLotteries = lotteryGame.purchaseAutoLotteries(14000) | ||
purchaseLotteries.lotteries.size shouldBe 14 | ||
} | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package lottery.domain | ||
|
||
import io.kotest.assertions.throwables.shouldThrow | ||
import io.kotest.core.spec.style.StringSpec | ||
|
||
class LotteryNumberTest : StringSpec({ | ||
"로또 숫자의 크기는 1이상 이여야한다." { | ||
shouldThrow<IllegalArgumentException> { | ||
LotteryNumber.get(0) | ||
} | ||
} | ||
|
||
"로또 숫자의 크기는 45이하여야 한다." { | ||
shouldThrow<IllegalArgumentException> { | ||
LotteryNumber.get(46) | ||
} | ||
} | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package lottery.domain | ||
|
||
import io.kotest.core.spec.style.StringSpec | ||
import io.kotest.matchers.shouldBe | ||
|
||
class LotteryPrizeTest : StringSpec({ | ||
"correctCount 갯수에 해당하는 LotteryPrize 를 가져와야한다." { | ||
LotteryPrize.get(correctCount = 3) shouldBe LotteryPrize.FORTH | ||
LotteryPrize.get(correctCount = 4) shouldBe LotteryPrize.THIRD | ||
LotteryPrize.get(correctCount = 5) shouldBe LotteryPrize.SECOND | ||
LotteryPrize.get(correctCount = 6) shouldBe LotteryPrize.FIRST | ||
} | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package lottery.domain | ||
|
||
import io.kotest.core.spec.style.StringSpec | ||
import io.kotest.matchers.shouldBe | ||
|
||
class LotteryRankTest : StringSpec({ | ||
"plusRank 호출시 해당하는 로또 등수를 올려주어야한다." { | ||
val lotteryRank = LotteryRank() | ||
lotteryRank.lotteriesRank[LotteryPrize.THIRD] shouldBe 0 | ||
lotteryRank.plusRank(LotteryPrize.THIRD) | ||
lotteryRank.lotteriesRank[LotteryPrize.THIRD] shouldBe 1 | ||
} | ||
|
||
"로또 구매 금액과 수익금으로 수익률(금액 / 구매금액)을 계산해 주어야한다." { | ||
val lotteryRank = LotteryRank() | ||
lotteryRank.calculateProfit(1000) shouldBe 0 | ||
lotteryRank.plusRank(LotteryPrize.FORTH) | ||
lotteryRank.calculateProfit(1000) shouldBe 5 | ||
} | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package lottery.domain | ||
|
||
import io.kotest.assertions.throwables.shouldThrow | ||
import io.kotest.core.spec.style.StringSpec | ||
import io.kotest.matchers.shouldBe | ||
|
||
class LotteryTest : StringSpec({ | ||
"자동 로또 생성을 할 경우의 숫자의 개수는 6개이다." { | ||
val lottery = Lottery.makeAutoLottery() | ||
lottery.lotteryNumbers.size shouldBe 6 | ||
} | ||
|
||
"로또는 번호는 중복돼서는 안된다." { | ||
val duplicatedNumbers = listOf(1, 2, 3, 1, 4, 5) | ||
shouldThrow<IllegalArgumentException> { | ||
Lottery(duplicatedNumbers.map { LotteryNumber.get(it) }.toSet()) | ||
} | ||
} | ||
|
||
"로또 한장의 금액은 1000원 이다." { | ||
Lottery.LOTTERY_PRICE shouldBe 1000 | ||
} | ||
|
||
"로또 두개를 비교했을때 맞는 개수를 정확하게 가져와야한다." { | ||
val numbers = listOf(1, 2, 3, 4, 5, 6) | ||
val winningNumbers = listOf(1, 2, 3, 8, 9, 10) | ||
val lottery = Lottery(numbers.map { LotteryNumber.get(it) }.toSet()) | ||
val winningLottery = WinningLottery(winningNumbers.map { LotteryNumber.get(it) }.toSet()) | ||
lottery.checkCorrectCount(winningLottery.winningNumbers) shouldBe 3 | ||
} | ||
}) |
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.
Controller
라고 정의하신LotteryGame
에purchaseAutoLotteries
로직이 생긴것 같아요.LotteryGame
를LotteryController
로 바꾸고 로직을 가지고 있는LotteryGame
을domain
에 만들어볼까요?