Skip to content

Commit 159dac5

Browse files
committed
feat: 로또 결과 메세지 출력
1 parent 4ad232c commit 159dac5

File tree

5 files changed

+82
-47
lines changed

5 files changed

+82
-47
lines changed

src/main/kotlin/lotto/LottoApplication.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package lotto
22

33
import lotto.domain.Cashier
44
import lotto.domain.Lotto
5+
import lotto.domain.Statistics
56
import lotto.stretagy.RandomLottoNumberListGenerator
67
import lotto.view.InputView
78
import lotto.view.OutputView
@@ -11,8 +12,12 @@ fun main() {
1112
val amount = InputView.purchaseAmount()
1213

1314
val numberOfLotto = Cashier.purchaseLotto(amount)
14-
val lottos = List(numberOfLotto) { Lotto.createLotto(randomNumberListGenerator.generate()) }
15-
OutputView.printPurchaseResult(lottos)
15+
val userLottos = List(numberOfLotto) { Lotto.createLotto(randomNumberListGenerator.generate()) }
16+
OutputView.printPurchaseResult(userLottos)
1617

1718
val winningNumbers = InputView.winningNumbers()
19+
val winningLotto = Lotto.createLotto(winningNumbers)
20+
21+
val lottoStatistics = Statistics.of(userLottos, winningLotto)
22+
OutputView.printLottoStatistics(lottoStatistics, amount)
1823
}

src/main/kotlin/lotto/constant/LottoRankConstant.kt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,3 @@ const val MATCH_COUNT_SIX = 6
99
const val MATCH_COUNT_FIVE = 5
1010
const val MATCH_COUNT_FOUR = 4
1111
const val MATCH_COUNT_THREE = 3
12-
const val FIRST_RANK_PRIZE = 2_000_000_000
13-
const val THIRD_RANK_PRIZE = 1_500_000
14-
const val FOURTH_RANK_PRIZE = 50_000
15-
const val FIFTH_RANK_PRIZE = 5_000
16-
const val NO_PRIZE = 0
Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
11
package lotto.domain
22

3-
data class Statistics(val rank: Int, val numberOfMatch: Int) {
3+
data class Statistics(val rank: Int, val matchCount: Int) {
4+
fun earnings(): Long {
5+
return (earningPriceByRanking() * matchCount).toLong()
6+
}
7+
8+
private fun earningPriceByRanking() =
9+
when (rank) {
10+
RANK_FIRST -> FIRST_RANK_EARNING
11+
RANK_SECOND -> SECOND_RANK_EARNING
12+
RANK_THIRD -> THIRD_RANK_EARNING
13+
RANK_FOURTH -> FOURTH_RANK_EARNING
14+
RANK_FIFTH -> FIFTH_RANK_EARNING
15+
else -> NO_RANK_EARNING
16+
}
17+
418
companion object {
5-
private const val RANK_FIRST_NUMBER = 1
6-
private const val RANK_SECOND_NUMBER = 2
7-
private const val RANK_THIRD_NUMBER = 3
8-
private const val RANK_FOURTH_NUMBER = 4
9-
private const val RANK_FIFTH_NUMBER = 5
19+
private const val RANK_FIRST = 1
20+
private const val RANK_SECOND = 2
21+
private const val RANK_THIRD = 3
22+
private const val RANK_FOURTH = 4
23+
private const val RANK_FIFTH = 5
1024

1125
private const val FIRST_RANK_EARNING = 2_000_000_000
1226
private const val SECOND_RANK_EARNING = 1_500_000
@@ -26,18 +40,11 @@ data class Statistics(val rank: Int, val numberOfMatch: Int) {
2640
return groupByRanking.map { Statistics(it.key, it.value.size) }.sortedByDescending { it.rank }
2741
}
2842

29-
fun earningsRatio(statistics: Statistics): Long {
30-
return calculateEarningRatioByRanking(statistics.rank) * statistics.numberOfMatch.toLong()
43+
fun calculateEarningRatio(
44+
statisticsList: List<Statistics>,
45+
amount: Int,
46+
): Double {
47+
return statisticsList.sumOf { it.earnings() }.toDouble() / amount
3148
}
32-
33-
private fun calculateEarningRatioByRanking(rank: Int) =
34-
when (rank) {
35-
RANK_FIRST_NUMBER -> FIRST_RANK_EARNING
36-
RANK_SECOND_NUMBER -> SECOND_RANK_EARNING
37-
RANK_THIRD_NUMBER -> THIRD_RANK_EARNING
38-
RANK_FOURTH_NUMBER -> FOURTH_RANK_EARNING
39-
RANK_FIFTH_NUMBER -> FIFTH_RANK_EARNING
40-
else -> NO_RANK_EARNING
41-
}
4249
}
4350
}
Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
11
package lotto.view
22

33
import lotto.domain.Lotto
4+
import lotto.domain.Statistics
45

56
class OutputView {
67
companion object {
78
private const val PURCHASE_RESULT_MESSAGE = "개를 구매했습니다."
9+
private const val RANK_FIRST_MATCH_COUNT_MESSAGE = "6개 일치 (2000000000원)"
10+
private const val RANK_THIRD_MATCH_COUNT_MESSAGE = "5개 일치 (1500000원)"
11+
private const val RANK_FOURTH_MATCH_COUNT_MESSAGE = "4개 일치 (50000원)"
12+
private const val RANK_FIFTH_MATCH_COUNT_MESSAGE = "3개 일치 (5000원)"
13+
private const val LOTTO_STATISTICS_TITLE = "당첨통계"
14+
private const val LOTTO_STATISTICS_SEPARATOR = "---------"
15+
private const val EARNING_RATIO_MESSAGE = "총 수익률은 %s 입니다. (기준이 1이기 때문에 결과적으로 %s라는 의미임)"
16+
private const val EARNING_RATIO_THRESHOLD = 1.0
17+
private const val PROFIT_MESSAGE = "이익"
18+
private const val BREAK_EVEN_MESSAGE = "본전"
19+
private const val LOSS_MESSAGE = "손해"
820

921
fun printPurchaseResult(purchasedLottos: List<Lotto>) {
1022
println("${purchasedLottos.size} $PURCHASE_RESULT_MESSAGE")
@@ -18,20 +30,36 @@ class OutputView {
1830
println()
1931
}
2032

21-
// fun printLottoStatistics(lottoStatistics: Map<RankType, Int>) {
22-
// println("당첨통계")
23-
// println("---------")
24-
// RankType.entries
25-
// .filter { it != RankType.NO_RANK }
26-
// .sortedBy { it.matchCount }
27-
// .forEach { rankType ->
28-
// val count = lottoStatistics[rankType] ?: 0
29-
// printLottoResult(rankType, count)
30-
// }
31-
// }
32-
//
33-
// private fun printLottoResult(rankType: RankType, count: Int) {
34-
// println("${rankType.matchCount}개 일치 (${rankType.price}원) - ${count}개")
35-
// }
33+
fun printLottoStatistics(
34+
statisticsList: List<Statistics>,
35+
amount: Int,
36+
) {
37+
println(LOTTO_STATISTICS_TITLE)
38+
println(LOTTO_STATISTICS_SEPARATOR)
39+
statisticsList.filter { it.rank in 1..5 && it.rank != 2 }
40+
.forEach { printLottoResult(it) }
41+
val earningRatio = Statistics.calculateEarningRatio(statisticsList, amount)
42+
println(EARNING_RATIO_MESSAGE.format(earningRatio, getProfitStatus(earningRatio)))
43+
}
44+
45+
private fun printLottoResult(statistics: Statistics) {
46+
println("${rankWithMatchCount(statistics.rank)} - ${statistics.matchCount}")
47+
}
48+
49+
private fun rankWithMatchCount(rank: Int): String =
50+
when (rank) {
51+
1 -> RANK_FIRST_MATCH_COUNT_MESSAGE
52+
3 -> RANK_THIRD_MATCH_COUNT_MESSAGE
53+
4 -> RANK_FOURTH_MATCH_COUNT_MESSAGE
54+
5 -> RANK_FIFTH_MATCH_COUNT_MESSAGE
55+
else -> ""
56+
}
57+
58+
private fun getProfitStatus(earningRatio: Double): String =
59+
when {
60+
earningRatio > EARNING_RATIO_THRESHOLD -> PROFIT_MESSAGE
61+
earningRatio == EARNING_RATIO_THRESHOLD -> BREAK_EVEN_MESSAGE
62+
else -> LOSS_MESSAGE
63+
}
3664
}
3765
}

src/test/kotlin/lotto/domain/StatisticsTest.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,32 +19,32 @@ class StatisticsTest : DescribeSpec({
1919
val actual: List<Statistics> = Statistics.of(userLottos, winningLotto)
2020

2121
actual[0].rank shouldBe 5
22-
actual[0].numberOfMatch shouldBe 0
22+
actual[0].matchCount shouldBe 0
2323

2424
actual[1].rank shouldBe 4
25-
actual[1].numberOfMatch shouldBe 0
25+
actual[1].matchCount shouldBe 0
2626

2727
actual[2].rank shouldBe 3
28-
actual[2].numberOfMatch shouldBe 1
28+
actual[2].matchCount shouldBe 1
2929

3030
actual[3].rank shouldBe 2
31-
actual[3].numberOfMatch shouldBe 0
31+
actual[3].matchCount shouldBe 0
3232

3333
actual[4].rank shouldBe 1
34-
actual[4].numberOfMatch shouldBe 3
34+
actual[4].matchCount shouldBe 3
3535
}
3636
}
3737
}
3838

3939
describe("earningsRatio test") {
4040
it("Integer Overflow 발생하지 않도록 헨들링") {
41-
val statistics = Statistics(rank = 1, numberOfMatch = 2)
41+
val statistics = Statistics(rank = 1, matchCount = 2)
4242
val actual = Statistics.earningsRatio(statistics)
4343
actual shouldBe 4_000_000_000
4444
}
4545

4646
it("3등 3장") {
47-
val statistics = Statistics(rank = 3, numberOfMatch = 3)
47+
val statistics = Statistics(rank = 3, matchCount = 3)
4848
val actual = Statistics.earningsRatio(statistics)
4949
actual shouldBe 150000
5050
}

0 commit comments

Comments
 (0)