Skip to content

Conversation

so528
Copy link

@so528 so528 commented Feb 13, 2025

Summary by CodeRabbit

  • 문서 업데이트
    • 로또 프로그램의 기능(번호 처리, 구입, 번호 생성, 당첨 번호 입력, 결과 확인 등)에 대한 상세한 설명이 포함된 문서를 추가했습니다.
  • 새로운 기능
    • 티켓 구매부터 번호 생성, 당첨 번호 입력, 결과 확인 및 수익률 계산까지 전 과정을 구현하여 로또 사용 경험을 강화했습니다.
  • 테스트 및 설정 개선
    • 사용자 입력 검증 및 테스트 범위를 확장하고, 커스텀 테스트 설정을 추가하여 시스템 신뢰성을 높였습니다.
  • 워크플로우 업데이트
    • GitHub Actions 워크플로우에 enum 모듈을 허용된 모듈 목록에 추가했습니다.
  • 내보내기 인터페이스 개선
    • Lotto 클래스만을 내보내는 명시적인 __all__ 선언을 추가하여 모듈의 내보내기 인터페이스를 명확히 했습니다.

Copy link

coderabbitai bot commented Feb 13, 2025

Walkthrough

이번 변경 사항은 Lotto 프로그램의 전반적인 문서화와 기능 향상을 포함합니다. docs/README.md에서는 Lotto 클래스의 주요 메소드와 기능이 체계적으로 정리되었으며, src/lotto/lotto.pysrc/lotto/main.py에서는 사용자 입력 검증, 번호 생성, 결과 판정 및 출력 등 Lotto 게임 로직이 보강되었습니다. 또한, pytest.ini에서는 사용자 정의 마커가 추가되었고, tests/lotto/test_main.py에서는 정상 및 예외 케이스에 대한 테스트가 확장되었습니다.

Changes

파일 변경 내용
docs/README.md Lotto 프로그램의 문서 추가: Lotto 번호 처리, 구매, 번호 생성, 당첨번호 입력, 결과 비교 및 출력 메소드 기술
pytest.ini 사용자 정의 마커 custom_name 추가 (테스트 설명용)
src/lotto/lotto.py, src/lotto/main.py Lotto 클래스 기능 보강: 생성자, 입력 검증, 랜덤 번호 생성, 당첨 번호 처리, 결과 체크 및 출력 메소드 추가. Prize enum 도입 및 main 함수 완전 구현
tests/lotto/test_main.py 기능 및 예외 테스트 추가: ERROR_MESSAGE 상수 정의 및 patch를 활용한 사용자 입력/랜덤 샘플 모킹
.github/workflows/check-no-external-libs.yml 허용된 모듈 목록에 enum 추가
src/lotto/__init__.py 불필요한 주석 제거 및 __all__ 선언 추가로 내보내는 엔티티 명시

Sequence Diagram(s)

sequenceDiagram
    participant M as Main
    participant L as Lotto
    M->>L: get_lotto_count()
    L-->>M: lotto_count
    M->>L: generate_lottos(lotto_count)
    L-->>M: purchased_lottos
    M->>L: get_winning_numbers()
    L-->>M: winning_numbers, bonus_number
    M->>L: check_results(purchased_lottos, winning_numbers, bonus_number)
    L-->>M: results
    M->>L: print_results(results, total_cost)
Loading

Poem

당근 듬뿍 먹고 달리는 토끼
코드 숲 속에 새 희망 심었네
번호들이 춤추며 빛나고
버그는 몰래 사라져 가네
🎉 코드의 변화, 함께 뛰놀자!

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
src/lotto/lotto.py (1)

102-108: 보너스 번호 검증 간소화 제안
Ruff 도구가 제안한 방식대로 조건식을 단순화하면 코드가 좀 더 간결해집니다.

-def _is_valid_bonus(bonus, numbers):
-    if bonus in numbers or not (1 <= bonus <= 45):
-        return False
-    return True
+def _is_valid_bonus(bonus, numbers):
+    return not (bonus in numbers or not (1 <= bonus <= 45))
🧰 Tools
🪛 Ruff (0.8.2)

105-107: Return the condition not (bonus in numbers or not 1 <= bonus <= 45) directly

Replace with return not (bonus in numbers or not 1 <= bonus <= 45)

(SIM103)

src/lotto/main.py (1)

11-15: 구매 정보 출력 시 비공개 멤버 직접 접근
lotto._numbers 대신 공용 메서드나 프로퍼티를 통해 접근하는 것이 유지보수와 캡슐화 측면에서 더 좋을 수 있습니다.

docs/README.md (1)

1-68: 마크다운 목록 들여쓰기 오류
markdownlint에서 MD007 경고가 다수 발생했습니다. 현재 문서 구조를 유지하면서 목록에 대한 들여쓰기를 재검토하거나, 규칙에 맞게(level 0 또는 2-4 스페이스) 조정하시는 것을 권장드립니다.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

7-7: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


10-10: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


16-16: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


17-17: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


20-20: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


26-26: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


29-29: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


35-35: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


36-36: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


39-39: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


42-42: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


45-45: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


48-48: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


54-54: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


57-57: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


60-60: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


66-66: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


67-67: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)

src/lotto/__init__.py (1)

1-2: __all__ 변수를 추가하여 공개 API를 명시적으로 정의하세요.

패키지 레벨에서 Lotto 클래스를 노출하는 것은 좋은 접근이지만, __all__ 변수를 사용하여 공개 API를 명시적으로 정의하는 것이 좋습니다.

다음과 같이 수정하는 것을 제안합니다:

 from .lotto import Lotto
-
+__all__ = ['Lotto']
🧰 Tools
🪛 Ruff (0.8.2)

1-1: .lotto.Lotto imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 100bec8 and 47504c3.

📒 Files selected for processing (5)
  • docs/README.md (1 hunks)
  • pytest.ini (1 hunks)
  • src/lotto/__init__.py (1 hunks)
  • src/lotto/lotto.py (1 hunks)
  • src/lotto/main.py (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • pytest.ini
🧰 Additional context used
🪛 Ruff (0.8.2)
src/lotto/lotto.py

105-107: Return the condition not (bonus in numbers or not 1 <= bonus <= 45) directly

Replace with return not (bonus in numbers or not 1 <= bonus <= 45)

(SIM103)

src/lotto/__init__.py

1-1: .lotto.Lotto imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

🪛 markdownlint-cli2 (0.17.2)
docs/README.md

7-7: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


10-10: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


16-16: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


17-17: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


20-20: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


26-26: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


29-29: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


35-35: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


36-36: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


39-39: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


42-42: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


45-45: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


48-48: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


54-54: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


57-57: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


60-60: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


66-66: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)


67-67: Unordered list indentation
Expected: 0; Actual: 3

(MD007, ul-indent)

🔇 Additional comments (22)
src/lotto/lotto.py (16)

2-2: 랜덤 모듈 불러오기 확인
random 모듈을 사용하여 로또 번호를 생성하는 방식이 적절해 보입니다.


6-6: 클래스 주석이 명확하게 작성됨
Lotto 클래스가 하는 역할과 목적을 한눈에 알 수 있어 가독성이 좋습니다.


13-19: 번호 검증 로직이 올바르게 구현됨
6개의 숫자, 중복 여부, 1~45 범위를 모두 검사하는 로직이 적절하게 구성되어 있습니다.


21-36: 사용자 입력 예외처리가 적절합니다
입력에서 예외가 발생할 경우 메시지를 출력 후, 예외를 다시 발생시켜 상위 호출부가 처리하도록 하는 흐름이 효과적입니다.


37-46: 금액 검증 로직이 정확합니다
1,000원 단위로 구매 가능한지, 최소 금액 검사까지 명확하여 사용자 오류를 방지하기에 충분합니다.


48-51: 무작위 번호 생성 로직
random.sample을 사용해 6개 중복 없는 숫자를 생성하는 접근 방식이 깔끔하고 효율적입니다.


52-56: 구매 개수만큼 로또 생성
리스트 컴프리헨션을 통한 반복 로직이 간단하고 명확하여 유지보수에도 유리합니다.


57-63: 당첨 번호 및 보너스 번호 입력
두 종류의 번호를 각각 입력받아 처리하고, 반환하는 구조가 직관적이고 사용하기 편리합니다.


64-76: 유효한 번호 입력을 위한 반복 구문
사용자가 올바른 형식으로 입력할 때까지 계속 시도하는 방식을 통해 예외 상황을 효과적으로 처리합니다.


77-84: 당첨 번호 검증 메서드
개수와 중복 여부, 범위를 모두 검사해 입력값을 확실히 제한하는 점이 좋습니다.


85-93: 보너스 번호 입력 처리
유효하지 않은 값이면 즉시 메시지를 출력하고 다시 시도하도록 하는 구조가 직관적입니다.


94-101: 보너스 번호 안전 입력
예외 발생 시 -1을 반환하고 이후 검증 메서드에서 걸러지도록 하는 설계가 안정적입니다.


109-125: 당첨 결과 집계 로직
구입한 로또 번호 각각에 대해 매칭을 계산한 결과를 딕셔너리에 축적하는 방식이 효율적입니다.


126-132: 로또 번호 매칭 계산
교집합을 통해 일치 개수를 바로 구하고, 보너스 번호 포함 여부를 별도로 검사하는 구조가 직관적입니다.


133-141: 당첨 등수 판별
일치 개수와 보너스 번호를 명확히 구분해 각 등수 키로 반환하는 흐름이 명쾌합니다.


142-163: 결과 출력 및 수익률 계산
등수별 당첨 금액 합산 후, 총 비용 대비 수익률 계산을 깔끔하게 구현해 사용성 및 가독성이 뛰어납니다.

src/lotto/main.py (6)

1-2: Lotto 클래스 임포트
lotto 모듈 내부의 Lotto 클래스 사용을 위한 기본적인 import가 잘 처리되어 있습니다.


5-7: 로또 구입 개수 획득
get_lotto_count() 호출을 통해 사용자 입력을 받고, 개수를 산출하는 흐름이 간단하며 가독성이 좋습니다.


8-10: 로또 번호 일괄 생성
구입 개수만큼 로또 번호를 자동 생성하는 generate_lottos 호출이 명확하고 효율적입니다.


16-17: 당첨 번호 및 보너스 번호 입력
get_winning_numbers() 함수로 사용자 입력을 일원화하여 처리하므로 유지보수가 편리합니다.


19-24: 당첨 결과 확인
check_results()의 반환값을 활용하여 등수별 로또 당첨 개수를 확인하는 구조가 깔끔합니다.


26-28: 결과 출력 및 총 비용 계산
lotto_count * 1000으로 비용을 구하고 print_results()를 통해 한 번에 통계를 보여주는 흐름이 명료합니다.

Copy link

codecov bot commented Feb 13, 2025

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

ℹ️ You can also turn on project coverage checks and project coverage reporting on Pull Request comment

Thanks for integrating Codecov - We've got you covered ☂️

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🔭 Outside diff range comments (1)
tests/lotto/test_main.py (1)

55-61: 🛠️ Refactor suggestion

예외 케이스 테스트를 더 추가하면 좋겠습니다.

현재는 잘못된 금액 입력에 대한 테스트만 있습니다. 다음과 같은 추가 예외 케이스도 테스트하면 좋을 것 같습니다:

  1. 음수 금액 입력
  2. 1000원 미만의 금액 입력
  3. 잘못된 당첨 번호 형식
  4. 범위를 벗어난 당첨 번호 (1-45 외의 숫자)
  5. 중복된 당첨 번호

예시 코드:

@pytest.mark.parametrize("invalid_input,expected_error", [
    ("-1000", ERROR_MESSAGE),
    ("500", ERROR_MESSAGE),
    ("1,2,3,4,5", ERROR_MESSAGE),  # 잘못된 당첨 번호 형식
    ("0,1,2,3,4,5", ERROR_MESSAGE),  # 범위 밖 번호
    ("1,1,2,3,4,5", ERROR_MESSAGE),  # 중복 번호
])
def test_다양한_예외_케이스(invalid_input, expected_error):
    with pytest.raises(ValueError, match=rf"{expected_error}"):
        with patch("builtins.input", return_value=invalid_input):
            main()
🧰 Tools
🪛 Ruff (0.8.2)

58-60: Use a single with statement with multiple contexts instead of nested with statements

(SIM117)

🧹 Nitpick comments (2)
tests/lotto/test_main.py (1)

9-52: 테스트 케이스를 더 작은 단위로 분리하는 것을 고려해보세요.

현재 테스트는 여러 기능을 한번에 검증하고 있습니다. 다음과 같이 개선하면 테스트 실패 시 원인을 더 쉽게 파악할 수 있습니다:

  1. 로또 구매 수량 검증
  2. 로또 번호 생성 검증
  3. 당첨 결과 계산 검증
  4. 수익률 계산 검증

예시 리팩토링:

def test_로또_구매_수량():
    with patch("builtins.input", return_value="8000"):
        # 구매 수량 검증 로직

def test_로또_번호_생성():
    with patch("random.sample") as mock_sample:
        # 번호 생성 검증 로직

def test_당첨_결과_계산():
    # 당첨 결과 검증 로직

def test_수익률_계산():
    # 수익률 검증 로직
src/lotto/lotto.py (1)

111-117: _is_valid_bonus 메서드를 더 간단하게 리팩토링할 수 있습니다.

조건문을 직접 반환하도록 개선하면 코드가 더 간결해질 것 같습니다.

다음과 같이 수정해보세요:

-    def _is_valid_bonus(bonus, numbers):
-        """보너스 번호 검증"""
-        if bonus in numbers or not 1 <= bonus <= 45:
-            return False
-        return True
+    def _is_valid_bonus(bonus, numbers):
+        """보너스 번호 검증"""
+        return not (bonus in numbers or not 1 <= bonus <= 45)
🧰 Tools
🪛 Ruff (0.8.2)

114-116: Return the condition not (bonus in numbers or not 1 <= bonus <= 45) directly

Replace with return not (bonus in numbers or not 1 <= bonus <= 45)

(SIM103)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 47504c3 and 9926aad.

📒 Files selected for processing (2)
  • src/lotto/lotto.py (1 hunks)
  • tests/lotto/test_main.py (1 hunks)
🧰 Additional context used
🪛 Ruff (0.8.2)
src/lotto/lotto.py

114-116: Return the condition not (bonus in numbers or not 1 <= bonus <= 45) directly

Replace with return not (bonus in numbers or not 1 <= bonus <= 45)

(SIM103)

🔇 Additional comments (7)
tests/lotto/test_main.py (1)

1-7: 테스트에 필요한 모듈과 상수가 적절히 정의되어 있습니다.

필요한 모듈들이 잘 임포트되어 있고, 에러 메시지 상수가 명확하게 정의되어 있습니다.

src/lotto/lotto.py (6)

5-11: 잘 구현된 Prize 열거형입니다!

당첨 등수를 명확하게 정의하고 있으며, 각 상수의 값이 적절하게 설정되어 있습니다.


14-20: 클래스 구조가 잘 설계되어 있습니다!

타입 힌트를 적절히 사용하고 있으며, 생성자에서 유효성 검사를 수행하는 것이 좋습니다.


21-55: 입력 유효성 검사가 철저히 구현되어 있습니다!

사용자 친화적인 오류 메시지와 함께 적절한 예외 처리가 이루어지고 있습니다.


56-65: 로또 번호 생성 로직이 효율적으로 구현되어 있습니다!

random.sample을 사용하여 중복 없는 번호를 생성하고, 정렬하여 반환하는 것이 좋습니다.


118-162: 당첨 결과 확인 로직이 체계적으로 구현되어 있습니다!

당첨 번호 비교와 등수 판별이 명확하게 구현되어 있으며, 코드가 잘 문서화되어 있습니다.


163-189: 결과 출력이 사용자 친화적으로 구현되어 있습니다!

당첨 통계와 수익률 계산이 명확하게 구현되어 있으며, 출력 형식이 보기 좋게 구성되어 있습니다.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
src/lotto/main.py (1)

6-32: main 함수에 예외 처리를 추가하면 좋겠습니다.

프로그램의 안정성을 위해 최상위 레벨에서 예외를 처리하는 것이 좋습니다.

다음과 같이 수정하는 것을 제안합니다:

 def main():
     """로또 프로그램 실행 함수"""
+    try:
         # 1. 로또 구입 개수 입력
         lotto_count = Lotto.get_lotto_count()
 
         # 2. 로또 번호 생성
         purchased_lottos = Lotto.generate_lottos(lotto_count)
 
         # 📌 요구된 형식으로 출력
         print(f"\n{lotto_count}개를 구매했습니다.")
         for lotto in purchased_lottos:
             print(f"{lotto.numbers}")
 
         # 3. 당첨 번호 및 보너스 번호 입력
         winning_numbers, bonus_number = Lotto.get_winning_numbers()
 
         # 4. 당첨 결과 확인
         results = Lotto.check_results(
             purchased_lottos,
             winning_numbers,
             bonus_number
         )
 
         # 5. 당첨 통계 및 수익률 출력
         total_cost = lotto_count * 1000  # 총 구입 금액
         Lotto.print_results(results, total_cost)
+    except Exception as e:
+        print(f"\n[ERROR] 프로그램 실행 중 오류가 발생했습니다: {e}")
+        return 1
+    return 0
src/lotto/lotto.py (3)

7-14: 상금 정보를 Prize Enum에 포함시키면 좋겠습니다.

상금 금액이 여러 곳에서 하드코딩되어 있습니다. Prize Enum에 상금 정보를 포함시키면 관리가 더 용이해질 것 같습니다.

다음과 같이 수정하는 것을 제안합니다:

 class Prize(Enum):
     """당첨 등수를 Enum으로 정의"""
-    THREE_MATCH = 3
-    FOUR_MATCH = 4
-    FIVE_MATCH = 5
-    FIVE_MATCH_BONUS = "5_bonus"
-    SIX_MATCH = 6
+    THREE_MATCH = (3, 5_000)
+    FOUR_MATCH = (4, 50_000)
+    FIVE_MATCH = (5, 1_500_000)
+    FIVE_MATCH_BONUS = (5, 30_000_000)
+    SIX_MATCH = (6, 2_000_000_000)
+
+    def __init__(self, match_count, prize_amount):
+        self.match_count = match_count
+        self.prize_amount = prize_amount

118-124: 불필요한 복잡성을 제거할 수 있습니다.

_is_valid_bonus 메서드의 반환문을 더 간단하게 작성할 수 있습니다.

다음과 같이 수정하는 것을 제안합니다:

     @staticmethod
     def _is_valid_bonus(bonus, numbers):
         """보너스 번호 검증"""
-        if bonus in numbers or not 1 <= bonus <= 45:
-            return False
-        return True
+        return not (bonus in numbers or not 1 <= bonus <= 45)
🧰 Tools
🪛 Ruff (0.8.2)

121-123: Return the condition not (bonus in numbers or not 1 <= bonus <= 45) directly

Replace with return not (bonus in numbers or not 1 <= bonus <= 45)

(SIM103)


28-36: 매직 넘버를 상수로 정의하면 좋겠습니다.

코드의 가독성과 유지보수성을 높이기 위해 매직 넘버를 상수로 정의하는 것이 좋습니다.

클래스 상단에 다음과 같은 상수를 추가하는 것을 제안합니다:

 class Lotto:
     """로또 번호 및 당첨 결과를 처리하는 클래스"""
 
+    NUMBERS_COUNT = 6
+    MIN_NUMBER = 1
+    MAX_NUMBER = 45
+    TICKET_PRICE = 1000
+
     def __init__(self, numbers: list[int]):

그리고 이를 활용하여 검증 로직을 수정합니다:

     def _validate(self, numbers: list[int]):
         """로또 번호 검증: 개수, 중복, 범위"""
-        if len(numbers) != 6:
+        if len(numbers) != self.NUMBERS_COUNT:
             raise ValueError("로또 번호는 정확히 6개여야 합니다.")
         if len(set(numbers)) != 6:
             raise ValueError("로또 번호에 중복이 있어서는 안 됩니다.")
-        if not all(1 <= num <= 45 for num in numbers):
+        if not all(self.MIN_NUMBER <= num <= self.MAX_NUMBER for num in numbers):
             raise ValueError("로또 번호는 1부터 45 사이여야 합니다.")
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 80c30cc and 2becc69.

📒 Files selected for processing (4)
  • .github/workflows/check-no-external-libs.yml (1 hunks)
  • src/lotto/__init__.py (1 hunks)
  • src/lotto/lotto.py (1 hunks)
  • src/lotto/main.py (1 hunks)
🧰 Additional context used
🪛 Ruff (0.8.2)
src/lotto/lotto.py

121-123: Return the condition not (bonus in numbers or not 1 <= bonus <= 45) directly

Replace with return not (bonus in numbers or not 1 <= bonus <= 45)

(SIM103)

🔇 Additional comments (2)
src/lotto/__init__.py (1)

1-5: 깔끔한 패키지 초기화 구현입니다!

패키지의 공개 인터페이스를 명확하게 정의하고 있습니다.

.github/workflows/check-no-external-libs.yml (1)

23-23: 표준 라이브러리 enum 모듈 추가가 적절합니다!

Prize Enum 구현을 위해 필요한 enum 모듈이 허용된 모듈 목록에 추가되었습니다.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
.github/workflows/check-no-external-libs.yml (2)

38-38: 에러 메시지의 한글화를 제안드립니다.

코드 내 주석은 한글로 작성되어 있는데 반해, 에러 메시지는 영어로 되어 있습니다. 일관성을 위해 에러 메시지도 한글화하는 것을 고려해보세요.

다음과 같이 변경하는 것을 제안드립니다:

-                                  raise SystemExit(f'❌ External library detected: {alias.name} in {file_path}')
+                                  raise SystemExit(f'❌ 외부 라이브러리가 감지되었습니다: {file_path} 파일에서 {alias.name}')
-                              raise SystemExit(f'❌ External library detected: {node.module} in {file_path}')
+                              raise SystemExit(f'❌ 외부 라이브러리가 감지되었습니다: {file_path} 파일에서 {node.module}')

Also applies to: 41-41


19-42: 스크립트의 모듈화를 제안드립니다.

현재 Python 스크립트가 워크플로우 파일 내에 직접 포함되어 있어 유지보수가 어려울 수 있습니다. 별도의 Python 파일로 분리하는 것을 고려해보세요.

.github/scripts/check_imports.py 파일을 생성하고 스크립트를 이동한 후, 워크플로우에서 이를 실행하는 방식을 제안드립니다.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2becc69 and 7d4386e.

📒 Files selected for processing (2)
  • .github/workflows/check-no-external-libs.yml (1 hunks)
  • src/lotto/__init__.py (0 hunks)
💤 Files with no reviewable changes (1)
  • src/lotto/init.py
🧰 Additional context used
🪛 YAMLlint (1.35.1)
.github/workflows/check-no-external-libs.yml

[error] 46-46: no new line character at the end of file

(new-line-at-end-of-file)

🔇 Additional comments (2)
.github/workflows/check-no-external-libs.yml (2)

1-16: 워크플로우 설정이 적절합니다!

GitHub Actions 워크플로우가 pull request 시 자동으로 실행되도록 잘 구성되어 있습니다.

🧰 Tools
🪛 actionlint (1.7.4)

10-10: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


13-13: the runner of "actions/setup-python@v4" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


23-23: enum 모듈 추가가 확인되었습니다.

allowed_modulesenum 모듈이 추가된 것이 확인되었습니다. 이는 Lotto 게임의 Prize 열거형을 위한 적절한 변경사항입니다.

for file in files:
if file.endswith('.py'):
check_imports(os.path.join(root, file))"
check_imports(os.path.join(root, file))"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

파일 끝에 개행 문자를 추가해주세요.

YAML 파일의 마지막 줄에는 개행 문자가 있어야 합니다. 이는 텍스트 파일의 표준 요구사항입니다.

파일의 마지막에 빈 줄을 추가해주세요.

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 46-46: no new line character at the end of file

(new-line-at-end-of-file)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/lotto/lotto.py (2)

7-14: 상금 정보를 Enum에 포함하는 것이 좋겠습니다.

각 등수별 상금 정보를 Prize Enum에 함께 정의하면 코드의 응집도를 높일 수 있습니다.

다음과 같이 수정하는 것을 제안합니다:

 class Prize(Enum):
     """당첨 등수를 Enum으로 정의"""
-    THREE_MATCH = 3
-    FOUR_MATCH = 4
-    FIVE_MATCH = 5
-    FIVE_MATCH_BONUS = "5_bonus"
-    SIX_MATCH = 6
+    THREE_MATCH = (3, 5_000)
+    FOUR_MATCH = (4, 50_000)
+    FIVE_MATCH = (5, 1_500_000)
+    FIVE_MATCH_BONUS = (5, 30_000_000)
+    SIX_MATCH = (6, 2_000_000_000)
+
+    def __init__(self, match_count, prize_amount):
+        self.match_count = match_count
+        self.prize_amount = prize_amount

119-123: 불리언 로직을 단순화할 수 있습니다.

현재 구현은 올바르지만, 더 간단하게 표현할 수 있습니다.

다음과 같이 수정하는 것을 제안합니다:

-        if bonus in numbers or not 1 <= bonus <= 45:
-            return False
-        return True
+        return not (bonus in numbers or not 1 <= bonus <= 45)
🧰 Tools
🪛 Ruff (0.8.2)

121-123: Return the condition not (bonus in numbers or not 1 <= bonus <= 45) directly

Replace with return not (bonus in numbers or not 1 <= bonus <= 45)

(SIM103)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7d4386e and 33ff896.

📒 Files selected for processing (2)
  • src/lotto/__init__.py (1 hunks)
  • src/lotto/lotto.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lotto/init.py
🧰 Additional context used
🪛 Ruff (0.8.2)
src/lotto/lotto.py

121-123: Return the condition not (bonus in numbers or not 1 <= bonus <= 45) directly

Replace with return not (bonus in numbers or not 1 <= bonus <= 45)

(SIM103)

🪛 GitHub Actions: Check Logic Separation
src/lotto/lotto.py

[error] 1-1: UI logic (print or input) should not be in src/lotto/lotto.py!

Comment on lines +38 to +51
def get_lotto_count():
"""로또 구입 금액 입력 및 예외 처리"""
try:
amount = input("로또 구입 금액을 입력하세요: ")
Lotto._validate_amount(amount)

amount = int(amount)
lotto_count = amount // 1000
print(f"{lotto_count}개의 로또를 구입합니다.")
return lotto_count

except ValueError as e:
print(e)
raise
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

UI 로직을 별도의 클래스로 분리해야 합니다.

현재 Lotto 클래스에 비즈니스 로직과 UI 로직이 혼재되어 있습니다. 단일 책임 원칙(SRP)을 준수하고 관심사를 분리하기 위해 UI 관련 로직을 별도의 클래스로 분리해야 합니다.

다음과 같은 구조로 리팩토링하는 것을 제안합니다:

  1. LottoUI 클래스 생성:
class LottoUI:
    @staticmethod
    def get_purchase_amount():
        return input("로또 구입 금액을 입력하세요: ")

    @staticmethod
    def print_purchase_count(count):
        print(f"{count}개의 로또를 구입합니다.")

    # 나머지 UI 관련 메서드들...
  1. Lotto 클래스에서는 순수한 비즈니스 로직만 유지:
class Lotto:
    @staticmethod
    def validate_amount(amount):
        # 검증 로직만 포함
        pass

    @staticmethod
    def get_lotto_count(amount):
        # 계산 로직만 포함
        return amount // 1000

Also applies to: 81-92, 102-109, 111-117, 175-196

Comment on lines +187 to +207
def print_winning_statistics(results):
"""당첨 개수를 출력"""
print(
f"3개 일치 (5,000원) - {results[Prize.THREE_MATCH]}\n"
f"4개 일치 (50,000원) - {results[Prize.FOUR_MATCH]}\n"
f"5개 일치 (1,500,000원) - {results[Prize.FIVE_MATCH]}\n"
"5개 일치, 보너스 볼 일치 (30,000,000원) - "
f"{results[Prize.FIVE_MATCH_BONUS]}\n"
f"6개 일치 (2,000,000,000원) - {results[Prize.SIX_MATCH]}개"
)

@staticmethod
def calculate_total_prize(results):
"""총 당첨 금액 계산"""
return (
results[Prize.THREE_MATCH] * 5000
+ results[Prize.FOUR_MATCH] * 50000
+ results[Prize.FIVE_MATCH] * 1500000
+ results[Prize.FIVE_MATCH_BONUS] * 30000000
+ results[Prize.SIX_MATCH] * 2000000000
)
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

상금 계산 로직을 Prize Enum과 통합하면 좋겠습니다.

상금 금액이 여러 곳에 하드코딩되어 있어 유지보수가 어려울 수 있습니다. Prize Enum에서 상금 정보를 가져오도록 수정하면 좋겠습니다.

Prize Enum 리팩토링 후 다음과 같이 수정할 수 있습니다:

@staticmethod
def calculate_total_prize(results):
    """총 당첨 금액 계산"""
    return sum(
        results[prize] * prize.prize_amount
        for prize in Prize
    )

@staticmethod
def print_winning_statistics(results):
    """당첨 개수를 출력"""
    for prize in Prize:
        print(f"{prize.match_count}개 일치 ({prize.prize_amount:,}원) - {results[prize]}개")

@swthewhite swthewhite changed the title [로또 게임]소현우 과제 제출합니다. [로또]소현우 과제 제출합니다. Feb 15, 2025
@swthewhite swthewhite changed the title [로또]소현우 과제 제출합니다. [로또] 소현우 과제 제출합니다. Feb 15, 2025
@swthewhite swthewhite changed the title [로또] 소현우 과제 제출합니다. [로또] 소현우 미션 제출합니다. Feb 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants