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

Step3 로또(2등) #1089

Merged
merged 20 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
ab95179
refactor: 사용하지 않는 패키지 임포트 제거
DuhanMo Nov 26, 2024
615a38a
refactor: intersect infix 함수 문법 적용
DuhanMo Nov 26, 2024
6c5edcb
test: 테스트 케이스 추가
DuhanMo Nov 26, 2024
7bdb298
refactor: 스태틱임포트 원복
DuhanMo Nov 26, 2024
04232d4
test: 로또번호 일치 수 반환 테스트 케이스 추가
DuhanMo Nov 26, 2024
db421e6
refactor: lottery 가 아닌 lotteryNumbers 를 갖도록 수정
DuhanMo Nov 26, 2024
ec0f6a3
refactor: Ticket::object 로 수정
DuhanMo Nov 26, 2024
116fd4c
refactor: divide operator fun 으로 수정
DuhanMo Nov 26, 2024
91b0460
refactor: getTotalReward 로직 내 타입 명시
DuhanMo Nov 26, 2024
717b1db
refactor: 로또 영문명을 Lotto 로 변경
DuhanMo Nov 26, 2024
53b8766
refactor: 로또 번호를 값 객체로 래핑, 로또 번호 리스트를 일급컬렉션으로 래핑
DuhanMo Nov 26, 2024
0dea87b
refactor: 로또 카운트를 값 객체로 래핑
DuhanMo Nov 26, 2024
e14add0
test: 보너스볼 로또번호 중복 예외 테스트
DuhanMo Nov 26, 2024
647ca42
test: 보너스볼 매치에 따른 순위 반환 테스트
DuhanMo Nov 27, 2024
0c9b168
feat: 보너스 볼 일치 출력
DuhanMo Nov 27, 2024
ebea44e
refactor: 변수명 수정
DuhanMo Nov 27, 2024
2c25c5b
refactor: comparable 구현
DuhanMo Nov 27, 2024
21ee37c
refactor: contains 을 in 으로 수정
DuhanMo Nov 27, 2024
1a96019
refactor: matchBonus 를 nullable 변수로 추출 후 matched 함수 추출
DuhanMo Nov 27, 2024
9cf802f
refactor: 테스트 전용 메서드 제거
DuhanMo Nov 27, 2024
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
27 changes: 26 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,29 @@
- [x] Numbers::validate 시 find api 사용
- [x] Parser::덧셈수 변수명 고려
- [x] StringAddCalculatorTest::커스텀 구분자 테스트 케이스 추가
- [x] Parser::parser 테스트 추가
- [x] Parser::parser 테스트 추가

# Step3 로또(2등)
## 기능 요구사항
- 2등을 위해 추가 번호를 하나 더 추첨한다.
- 당첨 통계에 2등도 추가해야 한다.

### Step2 - 리뷰 반영사항
- [x] LotteryNumbers::intersect infix 함수 문법 적용
- [x] TicketMachineTest::테스트 케이스 추가
- [x] LotteryApplication::스태틱임포트 원복
- [x] LotteryTest::로또번호 일치 수 반환 테스트 케이스 추가
- [x] WinningLottery::lotto 가 아닌 lotteryNumbers 를 갖도록 수정
- [x] Ticket::object 로 수정
- [x] Money::value class 로 수정
- [x] Money::divideBy operator fun 으로 수정
- [x] DrawResult::getTotalReward 로직 내 타입 명시

## 기능 구현 목록
- [x] 로또 영문명을 Lotto 로 변경
- [x] 로또 번호를 값 객체로 래핑한다.
- [x] 일급컬렉션으로 로또 번호 리스트를 래핑한다.
- [x] 보너스볼은 로또번호와 중복되지 않는다.
- [x] 5개 일치와 보너스볼 일치는 2등이다.
- [x] 5개 일치는 3등이다.
- [x] 보너스 볼 일치를 출력한다.
25 changes: 0 additions & 25 deletions src/main/kotlin/lottery/controller/LotteryApplication.kt

This file was deleted.

36 changes: 0 additions & 36 deletions src/main/kotlin/lottery/domain/DrawResult.kt

This file was deleted.

17 changes: 0 additions & 17 deletions src/main/kotlin/lottery/domain/Lottery.kt

This file was deleted.

7 changes: 0 additions & 7 deletions src/main/kotlin/lottery/domain/LotteryCount.kt

This file was deleted.

7 changes: 0 additions & 7 deletions src/main/kotlin/lottery/domain/LotteryMachine.kt

This file was deleted.

28 changes: 0 additions & 28 deletions src/main/kotlin/lottery/domain/LotteryNumbers.kt

This file was deleted.

28 changes: 0 additions & 28 deletions src/main/kotlin/lottery/domain/Money.kt

This file was deleted.

23 changes: 0 additions & 23 deletions src/main/kotlin/lottery/domain/RankReward.kt

This file was deleted.

3 changes: 0 additions & 3 deletions src/main/kotlin/lottery/domain/Ticket.kt

This file was deleted.

13 changes: 0 additions & 13 deletions src/main/kotlin/lottery/domain/TicketMachine.kt

This file was deleted.

9 changes: 0 additions & 9 deletions src/main/kotlin/lottery/domain/WinningLottery.kt

This file was deleted.

26 changes: 26 additions & 0 deletions src/main/kotlin/lotto/controller/LotteryApplication.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package lotto.controller

import lotto.domain.DrawResult
import lotto.domain.LottoMachine
import lotto.domain.Money
import lotto.domain.TicketMachine
import lotto.domain.WinningLotto
import lotto.view.InputView
import lotto.view.ResultView

fun main() {
val purchaseAmount = Money(InputView.inputPurchaseAmount())
val tickets = TicketMachine.exchange(purchaseAmount)
ResultView.printTicketCount(tickets)

val purchaseLotteries = LottoMachine.purchase(tickets)
ResultView.printLotteries(purchaseLotteries)

val winningLotto =
WinningLotto.create(
InputView.inputWinningLottoNumbers(),
InputView.inputWinningBonusNumber(),
)
val drawResult = DrawResult.from(winningLotto, purchaseLotteries)
ResultView.printStatistic(purchaseAmount, drawResult)
}
37 changes: 37 additions & 0 deletions src/main/kotlin/lotto/domain/DrawResult.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package lotto.domain

data class DrawResult(private val rankRewardLottoCountMap: Map<RankReward, LottoCount>) {
fun getProfitRate(purchaseAmount: Money): Double {
return getTotalReward() / purchaseAmount
}

fun getLottoCount(rankReward: RankReward): LottoCount {
return rankRewardLottoCountMap[rankReward] ?: LottoCount(0)
}

private fun getTotalReward(): Money {
return rankRewardLottoCountMap.entries.fold(Money.ZERO) { total: Money, (rankReward: RankReward, lottoCount: LottoCount) ->
val totalRewardPerRank: Money = rankReward.money * lottoCount.count
total + totalRewardPerRank
}
}

companion object {
fun from(
winningLotto: WinningLotto,
purchaseLotteries: List<Lotto>,
): DrawResult {
val rankRewardLottoCountMap =
purchaseLotteries
.map { lotto ->
val matchedCount = winningLotto.countMatchedNumber(lotto)
val matchBonus = winningLotto.matchBonus(lotto)
Comment on lines +27 to +28
Copy link

Choose a reason for hiding this comment

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

Winninglotto로 감싸둔 덕분에 깔끔하네요 👍

Copy link
Author

Choose a reason for hiding this comment

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

이전 단계에서 피드백 주신대로 해보았는데, 이번 단계 구현할 때 조금 더 깔끔해짐을 느꼈어요!
좋은 피드백 감사합니다🙇‍♂️🙂

RankReward.valueOf(matchedCount, matchBonus)
}
.groupingBy { it }
.eachCount()
.mapValues { LottoCount(it.value) }
return DrawResult(rankRewardLottoCountMap)
}
}
}
13 changes: 13 additions & 0 deletions src/main/kotlin/lotto/domain/Lotto.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package lotto.domain

data class Lotto(val lottoNumbers: LottoNumbers) {
override fun toString(): String {
return "$lottoNumbers"
}

companion object {
fun create(): Lotto {
return Lotto(LottoNumbers.create())
}
}
}
8 changes: 8 additions & 0 deletions src/main/kotlin/lotto/domain/LottoCount.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package lotto.domain

@JvmInline
value class LottoCount(val count: Int) {
override fun toString(): String {
return "$count"
}
}
7 changes: 7 additions & 0 deletions src/main/kotlin/lotto/domain/LottoMachine.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package lotto.domain

object LottoMachine {
fun purchase(tickets: List<Ticket>): List<Lotto> {
return List(tickets.size) { Lotto.create() }
}
}
24 changes: 24 additions & 0 deletions src/main/kotlin/lotto/domain/LottoNumber.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package lotto.domain

@JvmInline
value class LottoNumber(val number: Int) {
init {
require(number in LOTTO_NUMBER_RANGE) { "로또 번호는 $LOTTO_MIN_NUMBER 부터 $LOTTO_MAX_NUMBER 사이어야 합니다" }
}
Copy link

Choose a reason for hiding this comment

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

요것도 값 객체로 감싸주셨군요 👍


override fun toString(): String {
return "$number"
}

companion object {
private const val LOTTO_MIN_NUMBER = 1
private const val LOTTO_MAX_NUMBER = 45
private val LOTTO_NUMBER_RANGE = LOTTO_MIN_NUMBER..LOTTO_MAX_NUMBER

val ALL = LOTTO_NUMBER_RANGE.map { LottoNumber(it) }

fun create(): LottoNumber {
return LottoNumber(LOTTO_NUMBER_RANGE.random())
}
Comment on lines +24 to +26
Copy link

Choose a reason for hiding this comment

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

구현은 너무 잘 해주셔서... value class를 사용했을 떄의 장점을 공부해봐도 좋을 것 같아요. 아래는 힌트입니다!

image (show kotlin bytecode -> decompile 하면 java 코드를 볼 수 있습니다)

Copy link
Author

Choose a reason for hiding this comment

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

네! 좋은 의견감사해요😊
다시 확인해보니 해당 메서드는 테스트에서만 사용하고 있었네요🥲
해당 메서드를 제거하고 테스트하고자 했던 항목은 다른방식으로 작성해볼게요! 😀

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

class LottoNumbers(numbers: Set<LottoNumber>) {
val numbers: Set<LottoNumber>

init {
require(numbers.size == LOTTO_NUMBER_COUNT) { "로또 번호는 $LOTTO_NUMBER_COUNT 개이어야 합니다" }
this.numbers = numbers.sortedBy { it.number }.toSet()
Copy link

Choose a reason for hiding this comment

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

LottoNumber가 Comparable을 구현해도 좋을 것 같습니다!

Copy link
Author

Choose a reason for hiding this comment

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

네! 말씀하신대로 구현해볼게요😄

}

fun countMatchedNumber(other: LottoNumbers): Int {
return (numbers intersect other.numbers).size
}

fun containsNumber(other: LottoNumber): Boolean {
return numbers.contains(other)
Copy link

Choose a reason for hiding this comment

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

in 키워드가 conatins에 대응하는 operator 처럼 작동하기 때문에 other in numbers 처럼 사용이 가능해요. 취향껏 사용해주시면 되겠습니다.

Copy link
Author

@DuhanMo DuhanMo Nov 27, 2024

Choose a reason for hiding this comment

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

네! 좋은 키워드 알려주셔서 감사해요😊 반영하도록 하겠습니다!👍

}

override fun toString(): String {
return "$numbers"
}

companion object {
private const val LOTTO_NUMBER_COUNT = 6

fun create(): LottoNumbers {
return LottoNumbers(LottoNumber.ALL.shuffled().take(LOTTO_NUMBER_COUNT).toSet())
}

fun from(numbers: Set<Int>): LottoNumbers {
return LottoNumbers(numbers.map { LottoNumber(it) }.toSet())
}
}
}
Loading