Skip to content

Dev jihyun - 통계 기능 구현 #17

Merged
Turtle-Hwan merged 4 commits intomainfrom
dev-jihyun
Oct 26, 2025
Merged

Dev jihyun - 통계 기능 구현 #17
Turtle-Hwan merged 4 commits intomainfrom
dev-jihyun

Conversation

@jyun-KIM
Copy link
Member

주요 변경 사항

  1. 휴식 기록 추적 (src/state_manager.py)

    • StateManager에 history 리스트를 추가하여, 각 휴식 이벤트(사용된 도구, 시간,
      스트레스 변화 등)를 기록
    • 이 history는 서버가 재시작되어도 유지되도록 .chillmcp_state.json 파일에
      저장
    • add_history_event 메서드를 추가하여 휴식 도구 사용 시 관련 데이터를 history에
      추가하고 저장
  2. 통계 분석 로직 (src/statistics.py)

    • 통계 계산을 위한 src/statistics.py 모듈을 신규 생성
    • get_break_statistics 함수는 저장된 history 데이터를 읽어와 다음 항목들을
      분석
      • 총 휴식 횟수
      • 가장 자주 사용된 휴식 도구
      • 가장 자주 휴식을 취한 시간대
      • 도구별 휴식 횟수
  3. 통계 리포트 도구 (src/tools.py, src/server.py)

    • generate_report라는 새로운 도구를 추가
    • 이 도구는 statistics.get_break_statistics를 호출하여 통계 데이터를 가져온 후,
      사용자가 보기 쉬운 형태로 가공하여 출력
    • src/server.py에 generate_report 도구를 등록하여 API를 통해 통계 리포트를 받아볼
      수 있도록 함

@gemini-code-assist
Copy link

Summary of Changes

Hello @jyun-KIM, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 PR은 사용자의 휴식 습관을 추적하고 보고하는 새로운 통계 기능을 도입합니다. 휴식 이벤트 기록을 영구적으로 저장하고, 통계 분석을 위한 전용 모듈을 구현하며, 이러한 통계 데이터를 생성하고 표시하는 새로운 도구를 추가하는 것이 주요 내용입니다.

Highlights

  • 휴식 기록 추적: src/state_manager.py 파일에 history 리스트가 추가되어 각 휴식 이벤트(사용된 도구, 시간, 스트레스 및 보스 경고 변화 등)를 기록합니다. 이 기록은 .chillmcp_state.json 파일에 저장되어 서버 재시작 후에도 유지됩니다. 새로운 add_history_event 메서드가 추가되어 휴식 도구 사용 시 관련 데이터를 기록하고 저장합니다.
  • 통계 분석 로직: src/statistics.py라는 새로운 모듈이 생성되어 저장된 휴식 기록 데이터를 분석합니다. 이 모듈은 총 휴식 횟수, 가장 자주 사용된 휴식 도구, 가장 자주 휴식을 취한 시간대, 도구별 휴식 횟수 등을 계산합니다.
  • 통계 리포트 도구: src/tools.py에 generate_report라는 새로운 도구가 추가되었습니다. 이 도구는 statistics.get_break_statistics를 호출하여 통계 데이터를 가져온 후, 사용자가 보기 쉬운 형태로 가공하여 출력합니다. src/server.py에 generate_report 도구가 등록되어 API를 통해 통계 리포트를 받아볼 수 있습니다.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist
Copy link

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

@Turtle-Hwan
Copy link
Member

/gemini review

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

이 PR은 휴식 기록을 추적하고 통계를 생성하는 새로운 기능을 도입했습니다. 전반적으로 기능 구현의 방향은 좋지만, 몇 가지 개선점을 제안합니다. 주요 피드백은 statistics.py 모듈의 설계와 관련된 것으로, StateManager의 내부 구현에 대한 의존성을 줄여 더 안정적인 구조를 만드는 것에 중점을 두었습니다. 또한, 데이터 처리 시 발생할 수 있는 치명적인 오류를 수정하고, 코드의 일관성과 효율성을 높이기 위한 몇 가지 제안을 포함했습니다. 자세한 내용은 각 파일의 주석을 참고해주세요.

Comment on lines +36 to +41
return {
"total_breaks": total_breaks,
"most_common_tool": most_common_tool,
"most_common_hour": f"{most_common_hour}:00 - {most_common_hour+1}:00",
"breaks_by_tool": dict(tool_counter),
}

Choose a reason for hiding this comment

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

critical

history가 비어있을 경우 most_common_hour는 문자열 "N/A"가 됩니다. 이 경우 39번째 줄의 f-string에서 most_common_hour+1 연산이 TypeError를 발생시키는 버그가 있습니다. most_common_hour가 "N/A"인 경우를 별도로 처리해야 합니다.

Suggested change
return {
"total_breaks": total_breaks,
"most_common_tool": most_common_tool,
"most_common_hour": f"{most_common_hour}:00 - {most_common_hour+1}:00",
"breaks_by_tool": dict(tool_counter),
}
return {
"total_breaks": total_breaks,
"most_common_tool": most_common_tool,
"most_common_hour": f"{most_common_hour}:00 - {most_common_hour+1}:00" if most_common_hour != "N/A" else "N/A",
"breaks_by_tool": dict(tool_counter),
}

Comment on lines +18 to +23
if not STATE_FILE.exists():
return {"error": "No break history found."}

with open(STATE_FILE, 'r') as f:
data = json.load(f)
history = data.get("history", [])

Choose a reason for hiding this comment

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

high

이 함수는 상태 파일을 직접 읽어 StateManager의 내부 구현(JSON 파일 구조)에 강하게 의존하고 있습니다. 이는 StateManager의 저장 방식이 변경될 경우, 이 통계 모듈도 함께 수정해야 하는 문제를 야기합니다. 캡슐화 원칙을 지키기 위해, StateManager에 기록(history) 데이터를 제공하는 public 메소드(예: get_history())를 추가하고, 통계 모듈은 해당 메소드를 통해 데이터를 얻어오는 방식으로 리팩토링하는 것을 강력히 권장합니다. 이렇게 하면 statistics 모듈이 StateManager의 내부 구현으로부터 독립되어 더 안정적이고 유지보수하기 좋은 구조가 됩니다.

await state_manager.change_boss_alert(1)

# Save history (use negative stress_change for decrease)
state_manager.add_history_event("company_dinner", -stress_change if stress_change < 0 else stress_change, boss_alert_change)

Choose a reason for hiding this comment

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

high

company_dinner 이벤트의 스트레스 변화량을 기록하는 로직에 오류가 있습니다. stress_change 값이 음수일 때 (스트레스 감소), -stress_change를 전달하여 양수로 만들고 있습니다. 다른 도구들(execute_break_tool, chimaek 등)에서는 스트레스 감소를 음수 값으로 기록하고 있으므로, 일관성을 위해 stress_change 값을 그대로 전달해야 합니다. 현재 로직(-stress_change if stress_change < 0 else stress_changeabs(stress_change)와 동일)은 스트레스가 감소했음에도 불구하고 기록에는 스트레스가 증가한 것으로 잘못 남게 됩니다.

Suggested change
state_manager.add_history_event("company_dinner", -stress_change if stress_change < 0 else stress_change, boss_alert_change)
state_manager.add_history_event("company_dinner", stress_change, boss_alert_change)

# Use double underscore for true private variables
self.__stress_level: int = 0 # 0-100
self.__boss_alert_level: int = 0 # 0-5
self.history: list = []

Choose a reason for hiding this comment

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

medium

history 속성을 _history로 변경하여 클래스의 다른 내부 상태 변수(__stress_level, _last_stress_update 등)와의 명명 규칙 일관성을 유지하는 것이 좋습니다. 이는 이 변수가 클래스 내부용임을 나타냅니다. 이 변경을 적용하려면 이 파일의 236, 258, 273번째 줄에 있는 self.historyself._history로 함께 수정해야 합니다.

Suggested change
self.history: list = []
self._history: list = []

from datetime import datetime

# State file path (in project root)
STATE_FILE = Path(__file__).parent.parent / ".chillmcp_state.json"

Choose a reason for hiding this comment

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

medium

STATE_FILE 상수가 src/state_manager.py에도 정의되어 있어 코드가 중복됩니다. 유지보수성을 높이기 위해 state_manager에서 상수를 가져와 사용하는 것이 좋습니다. 예를 들어, from .state_manager import StateManager를 추가하고 STATE_FILE = StateManager.STATE_FILE로 사용할 수 있습니다.

Comment on lines +413 to +439
stats = statistics.get_break_statistics()

if "error" in stats:
return format_response(
break_summary=stats["error"],
stress_level=(await state_manager.get_state())["stress_level"],
boss_alert_level=(await state_manager.get_state())["boss_alert_level"],
tool_name="generate_report"
)

report = f"""**Breakdown of Your Break Habits**

- **Total Breaks Taken:** {stats["total_breaks"]}
- **Favorite Break Tool:** {stats["most_common_tool"]}
- **Busiest Break Time:** {stats["most_common_hour"]}

**Breaks by Tool:**
"""
for tool, count in stats["breaks_by_tool"].items():
report += f"- {tool}: {count}\n"

return format_response(
break_summary=report,
stress_level=(await state_manager.get_state())["stress_level"],
boss_alert_level=(await state_manager.get_state())["boss_alert_level"],
tool_name="generate_report"
)

Choose a reason for hiding this comment

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

medium

await state_manager.get_state()가 오류 처리 블록과 정상 처리 블록 양쪽에서 각각 호출되어 비효율적입니다. 특히 각 format_response 호출 내에서 stress_levelboss_alert_level을 얻기 위해 두 번씩 호출하는 부분은 개선이 필요합니다. 함수 시작 부분에서 한 번만 호출하여 결과를 변수에 저장하고, 두 블록에서 모두 재사용하면 코드가 더 간결해지고 효율적입니다.

    stats = statistics.get_break_statistics()
    state = await state_manager.get_state()

    if "error" in stats:
        return format_response(
            break_summary=stats["error"],
            stress_level=state["stress_level"],
            boss_alert_level=state["boss_alert_level"],
            tool_name="generate_report"
        )

    report = f"""**Breakdown of Your Break Habits**

    - **Total Breaks Taken:** {stats["total_breaks"]}
    - **Favorite Break Tool:** {stats["most_common_tool"]}
    - **Busiest Break Time:** {stats["most_common_hour"]}

    **Breaks by Tool:**
    """
    for tool, count in stats["breaks_by_tool"].items():
        report += f"- {tool}: {count}\n"

    return format_response(
        break_summary=report,
        stress_level=state["stress_level"],
        boss_alert_level=state["boss_alert_level"],
        tool_name="generate_report"
    )

@github-actions
Copy link

Test Results

47 tests   47 ✅  2m 20s ⏱️
 1 suites   0 💤
 1 files     0 ❌

Results for commit 1e058ab.

@Turtle-Hwan Turtle-Hwan merged commit 60260c4 into main Oct 26, 2025
2 checks passed
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