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

Step2 로또 자동 #595

Open
wants to merge 3 commits into
base: leehaeina
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,24 @@
# kotlin-lotto
# kotlin-lotto

## 자동 만들기 TODO
### 1. Input View
- [ ] 구입금액 입력받기
- [ ] 당첨번호 입력받기

### 2. Output View
- [ ] 생성된 로또번호 출력하기
- [ ] 당첨통계 출력하기

### 3. Service
- [X] 자동번호 등록하기
- [X] 랜덤번호 생성하기
- [X] 당첨번호 등록하기
- [x] 통계내기 - 당첨 개수 확인하기
- [ ] 통계내기 - 등수계산하기
- [ ] 통계내기 - 수익률계산하기

### 4. Domain
- [ ] 로또번호 - 구매번호
- [ ] 로또번호 - 당첨번호
- [ ] input - 구입금액
- [ ] 통계
44 changes: 44 additions & 0 deletions src/main/kotlin/LottoController.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import UI.InputView
import UI.OutputView
import domain.LottoInput
import domain.WinningLotto
import service.AutoNumberGenerator
import service.CalculateWinningStatistic
import service.RandomNumberGenerator
import service.WinningNumberRegister

class LottoController {
fun start() {
val inputView = InputView
val outputView = OutputView
Comment on lines +12 to +13
Copy link
Member

Choose a reason for hiding this comment

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

object는 변수에 할당 없이 바로 접근해서 메서드를 호출해보는 것은 어떨까요?

InputView.purchaseInputView()


val lottoInput = inputView.purchaseInputView()
outputView.ticketCountView(lottoInput.purchaseCount!!)

val randomNumberGenerator = RandomNumberGenerator(1, 45)
val autoNumberGenerator = AutoNumberGenerator(randomNumberGenerator)
val generatedLottos = autoNumberGenerator.saveAfterGenerate(lottoInput.purchaseCount)
outputView.purchaseLottoView(generatedLottos)

val winning = inputView.winningLottoInputView()
lottoInput.of(LottoInput(winningLotto = winning))

val winningNumberRegister = WinningNumberRegister(randomNumberGenerator)
val winningLotto = winningNumberRegister.register(lottoInput)

outputView.statisticDividerView()

val calculateWinningStatistic = CalculateWinningStatistic()
val ranks = calculateWinningStatistic.calculateRank(generatedLottos, winningLotto)
//output ranks statisticPrizeView
val prize = calculateWinningStatistic.calculatePrize(ranks)
val rate = calculateWinningStatistic.calculateRate(prize, lottoInput.purchaseAmount!!)
outputView.statisticRateView(rate)


}
}

fun main() {
LottoController().start()
}
21 changes: 21 additions & 0 deletions src/main/kotlin/UI/InputView.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package UI

import domain.LottoInput

object InputView {

fun purchaseInputView(): LottoInput {
println("구입금액을 입력해 주세요.")
val inputPrice = readln().trim()
return LottoInput(
purchaseAmount = inputPrice.toInt(),
purchaseCount = inputPrice.toInt() / 1000
)
}

fun winningLottoInputView(): List<Int> {
println("지난 주 당첨 번호를 입력해 주세요.")
val input = readln().trim()
return input.split(",").map { it.toInt() }
}
}
32 changes: 32 additions & 0 deletions src/main/kotlin/UI/OutputView.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package UI

import domain.LottoInput
import domain.PurchasedLotto
import domain.Rank

object OutputView {

fun ticketCountView(ticketCount: Int) {
println("${ticketCount}개를 구매했습니다.")
}

fun purchaseLottoView(purchasedLottos: List<PurchasedLotto>) {
purchasedLottos.forEach{
println(it.numbers.joinToString { "," })
}
}

fun statisticDividerView() {
println("당첨 통계")
println("---------")
}

fun statisticRateView(rate: Double) {
print("총 수익률은 ${rate}입니다.")
println("(기준이 1이기 때문에 결과적으로 ${if (rate >= 1) "이익" else "손해"}라는 의미임)")
}

fun statisticPrizeView(rank: Rank, winCount: Int) {
println("${rank.matchedCount}개 일치 (${rank.prize}원) - ${winCount}개")
}
}
16 changes: 16 additions & 0 deletions src/main/kotlin/domain/Lotto.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package domain

interface Lotto {
val numbers: List<Int>
Comment on lines +3 to +4
Copy link
Member

Choose a reason for hiding this comment

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

Int를 래핑해서 로또 번호 하나를 나타내는 객체를 만들어보는 것은 어떨까요?

val winningCount: Int?
}

class PurchasedLotto(override val numbers: List<Int>, override val winningCount: Int = 0) : Lotto {
fun calculateWinningCount(winningLotto: WinningLotto): Int{
return winningLotto.numbers.filter {
this.numbers.contains(it)
}.size
}
}

class WinningLotto(override val numbers: List<Int>, override val winningCount: Int? = null) : Lotto
Comment on lines +8 to +16
Copy link
Member

Choose a reason for hiding this comment

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

구매한 로또가 맞은 개수를 갖고 있는 게 어색해보여요.
지금은 로또와 당첨 로또가 동일하게 6개씩 숫자를 갖고있으니, 동일한 객체로 보여요 :)
Lotto는 하나의 객체로만 만들고, Lotto끼리 비교해서 몇 개가 맞았는지 개수를 반환하는 메서드를 만들어보는 것은 어떨까요?

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

class LottoInput(
val purchaseCount: Int? = 0,
val purchaseAmount: Int? = 0,
val winningLotto: List<Int>? = listOf()
) {
fun of(lottoInput: LottoInput): LottoInput {
return LottoInput(
purchaseCount = lottoInput.purchaseCount ?: this.purchaseCount,
purchaseAmount = lottoInput.purchaseAmount ?: this.purchaseAmount,
winningLotto = lottoInput.winningLotto ?: this.winningLotto
)
}
Comment on lines +3 to +14
Copy link
Member

Choose a reason for hiding this comment

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

기존에 있던 객체에서 다시 재활용하면서 객체를 복사하는 일은 불필요해보입니다.
InputView에서는 필요한 입력 값들만 반환하게 만들어보는 것은 어떨까요?

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

enum class Rank(val matchedCount: Int? = 0, val prize: Int = 0) {
FAIL(null, 0),
Comment on lines +3 to +4
Copy link
Member

Choose a reason for hiding this comment

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

enum class의 항목들이 이미 모든 값을 갖고 있기 때문에, default parameter를 갖지 않아도 되어 보입니다.
또, 상품이 없는 것은 null로 표현하기 보다 0 등의 숫자로 표현해보는 것은 어떨까요?

FOURTH(3, 5000),
THIRD(4, 50000),
SECOND(5, 1500000),
FIRST(6, 2000000000);
Comment on lines +7 to +8
Copy link
Member

Choose a reason for hiding this comment

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

숫자는 언더바 ( _ ) 로 구분해서 작성이 가능합니다.
또, 1등이 여러번 당첨 될 수도 있으니, Int 보단 Long을 활용해보는 것은 어떨까요?


fun isNotBoom(): Boolean = this != FAIL

companion object {
fun find(matchedCount: Int): Rank {
return values().find { it.matchedCount == matchedCount } ?: FAIL
}
}
}
3 changes: 3 additions & 0 deletions src/main/kotlin/domain/Statistic.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package domain

class Statistic(val prize : Int, val rate: Double)
15 changes: 15 additions & 0 deletions src/main/kotlin/service/AutoNumberGenerator.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package service

import domain.PurchasedLotto

class AutoNumberGenerator(
private val randomNumberGenerator: RandomNumberGenerator
) {
fun saveAfterGenerate(count: Int): List<PurchasedLotto>{
val result = mutableListOf<PurchasedLotto>()
for(i:Int in 0 until count){
result.add(PurchasedLotto(randomNumberGenerator.getGeneratedNumber()))
}
return result
Comment on lines +9 to +13
Copy link
Member

Choose a reason for hiding this comment

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

코틀린의 확장함수 map등을 활용해보는 것은 어떨까요?

}
}
16 changes: 16 additions & 0 deletions src/main/kotlin/service/CalculateWinningStatistic.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package service

import domain.PurchasedLotto
import domain.Rank
import domain.WinningLotto

class CalculateWinningStatistic {
fun calculateRank(candidate: List<PurchasedLotto>, winningLotto: WinningLotto): List<Rank> =
candidate.map { Rank.find(it.calculateWinningCount(winningLotto)) }

fun calculatePrize(ranks: List<Rank>): Int =
Rank.values().fold(0) { totalPrize, nowRank -> totalPrize + nowRank.prize }

fun calculateRate(prize: Int, purchase: Int): Double =
prize.toDouble() / prize
}
13 changes: 13 additions & 0 deletions src/main/kotlin/service/RandomNumberGenerator.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package service

class RandomNumberGenerator(override val startNumber: Int, override val endNumber: Int) :
NumberGenerator {
override fun getGeneratedNumber(): List<Int> =
(startNumber..endNumber).map { it }.shuffled().slice(0..5)
}

interface NumberGenerator {
fun getGeneratedNumber(): List<Int>
val startNumber: Int
val endNumber: Int
}
12 changes: 12 additions & 0 deletions src/main/kotlin/service/WinningNumberRegister.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package service

import domain.LottoInput
import domain.WinningLotto

class WinningNumberRegister(
private val randomNumberGenerator: RandomNumberGenerator
) {
fun register(input : LottoInput): WinningLotto{
return WinningLotto(numbers = input.winningLotto!!)
}
}
19 changes: 19 additions & 0 deletions src/test/kotlin/AutoNumberGeneratorTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import org.junit.jupiter.api.Test
import service.AutoNumberGenerator
import service.RandomNumberGenerator

class AutoNumberGeneratorTest {

var autoNumberGenerator: AutoNumberGenerator
var randomNumberGenerator = RandomNumberGenerator(1,45)
init {
autoNumberGenerator = AutoNumberGenerator(randomNumberGenerator)
}
@Test
fun `자동번호생성테스트`() {
val result = autoNumberGenerator.saveAfterGenerate(3)
for (i: Int in 0 until result.size) {
println(result.get(i).numbers)
}
}
}
16 changes: 16 additions & 0 deletions src/test/kotlin/LottoTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import domain.PurchasedLotto
import domain.WinningLotto
import org.junit.jupiter.api.Test

class LottoTest {

@Test
fun `calculateWinningLottoTest`(){
val target = listOf<Int>(1,2,3,4,5,6)
val winning = listOf<Int>(1,6,7,8,9,10)
val winningLotto = WinningLotto(numbers = winning)
val purchasedLotto = PurchasedLotto(numbers = target)
val winningCount = purchasedLotto.calculateWinningCount(winningLotto)
println(winningCount)
}
}
11 changes: 11 additions & 0 deletions src/test/kotlin/RandomNumberGeneratorTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import org.junit.jupiter.api.Test
import service.RandomNumberGenerator

class RandomNumberGeneratorTest {

@Test
fun `랜덤하게`(){
val randomNumberGenerator = RandomNumberGenerator(1,45)
println(randomNumberGenerator.getGeneratedNumber())
}
}