-
Notifications
You must be signed in to change notification settings - Fork 5
[로또] 원영진 미션 제출합니다. #5
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
base: main
Are you sure you want to change the base?
Changes from all commits
b857f56
2865daa
e9ae163
df8e259
d2f5861
5139c36
1371e6f
53ac279
4a9fd97
04230f5
655b819
c0b132b
9cb1af2
57a45ba
a406f68
b063e99
9e947cc
8178407
ab9302b
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,75 @@ | ||
## 기능 요구 사항 | ||
- [X] 입력 기능 | ||
- [X] 로또 구입 금액 입력 | ||
- [X] 당첨 번호 입력. 번호는 쉽표(',')를 기준으로 구분 | ||
- [X] 보너스 번호 입력 | ||
|
||
- [ ] 출력 기능 | ||
- [X] 구입 금액 입력 요구 문구 "구입금액을 입력해 주세요." | ||
- [X] 발행한 로또 수량 출력 | ||
- [X] 발행한 로또 수량만큼 번호 출력. 번호는 오름차순으로 정렬하여 출력 | ||
- [ ] 당첨 내역 출력 | ||
- [ ] 수익률 출력, 수익률은 소수점 둘째 자리에서 반올림 | ||
- [ ] 예외 상황 시 에러 문구 출력. 에러 문구는 "[ERROR]"로 시작 | ||
|
||
- [ ] 컴퓨터 기능 | ||
- [X] 구입 금액에 해당하는 만큼 로또 발행 | ||
- [X] 로또는 6자리이며, 범위는 1 ~ 45 사이 정수 | ||
- [X] 사용자가 구매한 로또 번호와 당첨 번호 비교 | ||
- [ ] 당첨 내역 및 수익률 계산 | ||
|
||
- [ ] 당첨 기준 및 금액 | ||
- [ ] 1등: 6개 번호 일치 / 2,000,000,000원 | ||
- [ ] 2등: 5개 번호 + 보너스 번호 일치 / 30,000,000원 | ||
- [ ] 3등: 5개 번호 일치 / 1,500,000원 | ||
- [ ] 4등: 4개 번호 일치 / 50,000원 | ||
- [ ] 5등: 3개 번호 일치 / 5,000원 | ||
|
||
- [X] 예외 처리 기능 | ||
- [X] 사용자가 잘못된 값을 입력할 경우 ValueError를 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받음 | ||
- [X] 로또 구입 금액 입력 예외 사항 | ||
- [X] int형이 아닌 경우 | ||
- [X] 양의 정수가 아닌 경우 | ||
- [X] 1,000원 단위가 아닌 경우 | ||
- [X] 당첨 번호 입력 예외 사항 | ||
- [X] 정수가 아닌 것이 포함된 경우 | ||
- [X] 당첨 번호 길이가 6자리가 아닌 경우 | ||
- [X] 번호 범위가 1 ~ 45를 벗어날 경우 | ||
- [X] 당첨 번호가 중복될 경우 | ||
- [X] 보너스 번호 입력 예외사항 | ||
- [X] 정수가 아닌 경우 | ||
- [X] 번호 범위가 1 ~ 45를 벗어날 경우 | ||
- [X] 당첨 번호와 중복될 경우 | ||
|
||
## 기능 추가 | ||
1. is_number() | ||
> 입력 값이 정수인지 검증하는 함수 | ||
2. validate_input_prchase_amount() | ||
> 구매 금액 입력에 대한 검증 함수 | ||
3. input_purchase_amount() | ||
> 구매 금액을 입력받는 함수 | ||
4. generate_lotto_quantity() | ||
> 구매 가능한 로또 개수 계산 함수 | ||
5. Lotto.issuance_lotto() | ||
> 로또 발행 함수 | ||
6. convert_to_list() | ||
> 입력 값을 list 형식으로 변환하는 함수 | ||
7. input_winning_numbers() | ||
> 당첨 번호를 입력받는 함수 | ||
8. Lotto._validate() | ||
> 당첨 번호를 검증하는 함수 | ||
9. input_bonus_number() | ||
> 보너스 번호를 입력받는 함수 | ||
10. Lotto.validate_bonus_number() | ||
> 보너스 번호를 검증하는 함수 | ||
11. Lotto.compare_winning_number() | ||
> 당첨 번호와 발행 번호를 비교하는 함수 | ||
12. Lotto.compare_bonus_number() | ||
> 보너스 번호와 발행 번호를 비교하는 함수 | ||
13. Lotto.calculate_result() | ||
> 발행한 로또를 순서대로 당첨 번호, 보너스 번호 비교 함수를 실행하는 함수 | ||
|
||
|
||
## 오류 수정 | ||
|
||
## 기능 수정 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,95 @@ | ||
from typing import List | ||
from enum import Enum | ||
import random | ||
|
||
|
||
LOTTO_SIZE = 6 # 로또 길이 매직넘버상수 | ||
LOTTO_NUMBER_RANGE = range(1, 46) # 로또 숫자 범위 매직넘버상수 | ||
|
||
|
||
class Lotto: | ||
def __init__(self, numbers: List[int]): | ||
def __init__(self, numbers: list[int] = None): | ||
if numbers is None: # numbers가 주어지지 않으면 자동으로 생성 | ||
numbers = self.issuance_lotto() | ||
self._validate(numbers) | ||
self._numbers = numbers | ||
self.bonus_number = int | ||
self.numbers_list = list[list] | ||
self.result_list = list[int] | ||
self.statistics_list = list[list] | ||
|
||
def _validate(self, numbers: list[int]): | ||
if len(numbers) != LOTTO_SIZE: | ||
raise ValueError("[ERROR] 당첨 번호는 6자리입니다.") | ||
elif not all(num in LOTTO_NUMBER_RANGE for num in numbers): | ||
raise ValueError("[ERROR] 당첨 번호는 1 ~ 45 사이여야 합니다.") | ||
elif not all(numbers.count(num) == 1 for num in numbers): | ||
raise ValueError("[ERROR] 당첨 번호는 중복될 수 없습니다.") | ||
|
||
def validate_bonus_number(self, number: int): | ||
self.bonus_number = number | ||
if self.bonus_number in self._numbers: | ||
raise ValueError("[ERROR] 보너스 번호는 당첨 번호와 중복될 수 없습니다.") | ||
elif self.bonus_number not in LOTTO_NUMBER_RANGE: | ||
raise ValueError("[ERROR] 보너스 번호는 1 ~ 45 사이여야 합니다.") | ||
|
||
@staticmethod | ||
def issuance_lotto(): | ||
"""랜덤한 6자리 로또 번호 생성 후 정렬하여 반환""" | ||
value = sorted(random.sample(LOTTO_NUMBER_RANGE, LOTTO_SIZE)) | ||
return value | ||
|
||
def __str__(self): | ||
"""str 형식으로 변환하여 반환""" | ||
return str(self._numbers) | ||
|
||
def get_numbers(self): | ||
"""로또 번호 리스트 반환""" | ||
return self._numbers | ||
|
||
def compare_winning_number(self, numbers: list[int]): | ||
"""당첨 번호와 발행 번호를 비교""" | ||
count = 0 | ||
for i in numbers: | ||
if i in self._numbers: | ||
count += 1 | ||
return count | ||
|
||
def compare_bonus_number(self, numbers: list[int]): | ||
"""보너스 번호와 발행 번호를 비교""" | ||
if self.bonus_number in numbers: | ||
return 1 | ||
return 0 | ||
|
||
def calculate_result(self, numbers_list: list[list]): | ||
"""발행한 로또를 순서대로 당첨 번호, 보너스 번호와 비교""" | ||
self.numbers_list = numbers_list | ||
self.result_list = [0 for _ in range(len(numbers_list))] | ||
for i in range(len(self.result_list)): | ||
count_winning = self.compare_winning_number(self.numbers_list[i]) | ||
count_bonus = self.compare_bonus_number(self.numbers_list[i]) | ||
self.result_list[i] = [count_winning, count_bonus] | ||
return self.result_list | ||
|
||
|
||
class Score(Enum): | ||
FIRST = (6, 0, 2000000000) # 6개 일치, 보너스 X, 1등 | ||
SECOND = (5, 1, 30000000) # 5개 일치, 보너스 O, 2등 | ||
THIRD = (5, 0, 1500000) # 5개 일치, 보너스 X, 3등 | ||
FOURTH = (4, 0, 50000) # 4개 일치, 보너스 X, 4등 | ||
FIFTH = (3, 0, 5000) # 3개 일치, 보너스 X, 5등 | ||
NONE = (0, 0, 0) # 당첨되지 않음 | ||
|
||
def _validate(self, numbers: List[int]): | ||
if len(numbers) != 6: | ||
raise ValueError | ||
def __init__(self, m_count, b_match, prize): | ||
self.m_count = m_count # 맞춘 숫자 개수 | ||
self.b_match = b_match # 보너스 번호 일치 여부 | ||
self.prize = prize # 상금 | ||
|
||
# TODO: 추가 기능 구현 | ||
@classmethod | ||
def get_score(cls, m_count, b_match): | ||
""" | ||
당첨 번호 개수와 보너스 번호 여부를 받아 해당하는 Score 반환 | ||
""" | ||
for score in cls: | ||
if score.m_count == m_count and score.b_match == b_match: | ||
return score | ||
return cls.NONE # 당첨되지 않은 경우 |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,6 +1,118 @@ | ||||||||||||||||||||||||||||||||||
from lotto.lotto import Lotto | ||||||||||||||||||||||||||||||||||
from lotto.lotto import Score | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
LOTTO_EACH_PRICE = 1000 # 로또 구입 금액 단위 매직넘버상수 | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
# data가 정수인지 검증 함수 | ||||||||||||||||||||||||||||||||||
def is_number(data): | ||||||||||||||||||||||||||||||||||
try: | ||||||||||||||||||||||||||||||||||
return int(data) | ||||||||||||||||||||||||||||||||||
except ValueError as e: | ||||||||||||||||||||||||||||||||||
raise ValueError("[ERROR] 정수만 입력해주세요.") from e | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
# 구입 금액 입력 검증 함수 | ||||||||||||||||||||||||||||||||||
def validate_purchase_amount(data): | ||||||||||||||||||||||||||||||||||
purchase_amount = is_number(data) # 입력 값이 정수인지 검증 | ||||||||||||||||||||||||||||||||||
if purchase_amount <= 0: # 입력 값이 양의 정수인지 검증 | ||||||||||||||||||||||||||||||||||
raise ValueError("[ERROR] 구입 금액은 양의 정수 입니다.") | ||||||||||||||||||||||||||||||||||
elif purchase_amount % LOTTO_EACH_PRICE != 0: # 입력 값이 1,000원 단위인지 검증 | ||||||||||||||||||||||||||||||||||
raise ValueError("[ERROR] 구입 금액을 1,000원 단위로 입력해 주세요.") | ||||||||||||||||||||||||||||||||||
return purchase_amount # 검증 통과 | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
def input_purchase_amount(): # 구입 금액 입력 함수 | ||||||||||||||||||||||||||||||||||
print("구입금액을 입력해 주세요.") | ||||||||||||||||||||||||||||||||||
purchase_amount = input() | ||||||||||||||||||||||||||||||||||
purchase_amount = validate_purchase_amount(purchase_amount) # 구입 금액 검증 | ||||||||||||||||||||||||||||||||||
return purchase_amount | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
# 구매 가능한 로또 개수 계산 | ||||||||||||||||||||||||||||||||||
def generate_lotto_quantity(purcahse_amount): | ||||||||||||||||||||||||||||||||||
lotto_quantity = purcahse_amount // LOTTO_EACH_PRICE | ||||||||||||||||||||||||||||||||||
print("\n{0}개를 구매했습니다.".format(lotto_quantity)) | ||||||||||||||||||||||||||||||||||
return lotto_quantity | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
# 입력 값을 list 형식으로 변환해주는 함수 | ||||||||||||||||||||||||||||||||||
def convert_to_list(data): | ||||||||||||||||||||||||||||||||||
try: | ||||||||||||||||||||||||||||||||||
data = list(map(int, data.replace(" ", "").split(","))) | ||||||||||||||||||||||||||||||||||
return data | ||||||||||||||||||||||||||||||||||
except ValueError as e: | ||||||||||||||||||||||||||||||||||
raise ValueError("[ERROR] 번호는 정수로 이루어져 있어야 합니다.") from e | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
Comment on lines
+40
to
+47
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. 🛠️ Refactor suggestion 입력값 검증 강화 및 테스트 추가가 필요합니다.
def convert_to_list(data):
try:
+ if not data.strip():
+ raise ValueError("[ERROR] 빈 입력값은 허용되지 않습니다.")
data = list(map(int, data.replace(" ", "").split(",")))
return data
except ValueError as e:
raise ValueError("[ERROR] 번호는 정수로 이루어져 있어야 합니다.") from e 📝 Committable suggestion
Suggested change
🧰 Tools🪛 GitHub Check: codecov/patch[warning] 45-46: src/lotto/main.py#L45-L46 |
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
# 당첨 번호를 입력받고 검증하는 함수 | ||||||||||||||||||||||||||||||||||
def input_winning_numbers(): | ||||||||||||||||||||||||||||||||||
print("\n당첨 번호를 입력해 주세요.") | ||||||||||||||||||||||||||||||||||
winning_numbers = input() # 당첨 번호 입력 | ||||||||||||||||||||||||||||||||||
winning_numbers = convert_to_list(winning_numbers) # 당첨 번호 list형으로 변경 | ||||||||||||||||||||||||||||||||||
lotto = Lotto(winning_numbers) # 당첨 번호 검증 | ||||||||||||||||||||||||||||||||||
return lotto | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
# 보너스 번호를 입력받고 검증하는 함수 | ||||||||||||||||||||||||||||||||||
def input_bonus_number(lotto): | ||||||||||||||||||||||||||||||||||
print("\n보너스 번호를 입력해 주세요.") | ||||||||||||||||||||||||||||||||||
bouns_number = input() # 보너스 번호 입력 | ||||||||||||||||||||||||||||||||||
bouns_number = is_number(bouns_number) # 보너스 번호를 int형으로 변환 | ||||||||||||||||||||||||||||||||||
lotto.validate_bonus_number(bouns_number) # 보너스 번호 검증증 | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
def just_print(Score, score_count): | ||||||||||||||||||||||||||||||||||
# 결과 출력 | ||||||||||||||||||||||||||||||||||
for score in Score: | ||||||||||||||||||||||||||||||||||
if score == Score.NONE: | ||||||||||||||||||||||||||||||||||
continue # NONE 등급(낙첨)은 출력하지 않음 | ||||||||||||||||||||||||||||||||||
description = f"{score.m_count}개 일치" | ||||||||||||||||||||||||||||||||||
if score.b_match == 1: | ||||||||||||||||||||||||||||||||||
description += ", 보너스 볼 일치" | ||||||||||||||||||||||||||||||||||
print(f"{description} ({format(score.prize, ',d')}원)", end="") | ||||||||||||||||||||||||||||||||||
print(f" - {score_count[score]}개") | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
def print_result(result_list, purchase_amount): | ||||||||||||||||||||||||||||||||||
print("\n당첨 통계\n---") | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
# 등수별 당첨 개수 저장 딕셔너리 초기화 | ||||||||||||||||||||||||||||||||||
score_count = {score: 0 for score in Score if score != Score.NONE} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
# 당첨 개수 세기 | ||||||||||||||||||||||||||||||||||
for match_count, bonus_match in result_list: | ||||||||||||||||||||||||||||||||||
score = Score.get_score(match_count, bonus_match) | ||||||||||||||||||||||||||||||||||
if score != Score.NONE: | ||||||||||||||||||||||||||||||||||
score_count[score] += 1 | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
just_print(Score, score_count) | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
# 총 당첨 금액 계산 | ||||||||||||||||||||||||||||||||||
total_prize = sum(score.prize * cnt for score, cnt in score_count.items()) | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
# 수익률 계산 및 출력 | ||||||||||||||||||||||||||||||||||
revenue_rate = (total_prize / purchase_amount) * 100 | ||||||||||||||||||||||||||||||||||
print(f"총 수익률은 {revenue_rate:.1f}%입니다.") | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
def main(): | ||||||||||||||||||||||||||||||||||
# TODO: 프로그램 구현 | ||||||||||||||||||||||||||||||||||
pass | ||||||||||||||||||||||||||||||||||
purchase_amount = input_purchase_amount() # 구입 금액 입력 | ||||||||||||||||||||||||||||||||||
l_quantity = generate_lotto_quantity(purchase_amount) # 로또 수량 계산산 | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
issu_l_list = [Lotto.issuance_lotto() for _ in range(l_quantity)] # 로또 발행 | ||||||||||||||||||||||||||||||||||
for lotto in issu_l_list: # 발행된 로또 출력 | ||||||||||||||||||||||||||||||||||
print(lotto) | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
lotto = input_winning_numbers() # 당첨 번호 입력 | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
input_bonus_number(lotto) # 보너스 번호 입력 | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
result_list = lotto.calculate_result(issu_l_list) | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
print_result(result_list, purchase_amount) | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
if __name__ == "__main__": | ||||||||||||||||||||||||||||||||||
main() |
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.
🛠️ Refactor suggestion
로또 개수 생성 함수
purcahse_amount
파라미터의 철자가 오타로 보이며, 변수 명을purchase_amount
로 수정하는 것을 권장합니다.📝 Committable suggestion