""" Agregator — przetwarza eventy GitLab na statystyki per użytkownik. """ from collections import defaultdict from dataclasses import dataclass, field @dataclass class UserStats: name: str = "" username: str = "" user_id: int = 0 commits: int = 0 merge_requests: int = 0 comments: int = 0 other: int = 0 @property def total_contributions(self) -> int: return self.commits + self.merge_requests + self.comments + self.other class Aggregator: def __init__(self): self._stats: dict[int, UserStats] = defaultdict(UserStats) def process_events(self, events: list[dict]) -> None: """ Przetwarza listę eventów GitLab i agreguje statystyki. Typy akcji: - pushed → commit - merged → merge request - commented → komentarz - created/closed/reopened → inne """ for event in events: author = event.get("author") or {} uid = author.get("id") or event.get("author_id") if not uid: continue stats = self._stats[uid] stats.user_id = uid stats.name = author.get("name", stats.name) stats.username = author.get("username", stats.username) action = event.get("action_name", "") if action == "pushed to" or action == "pushed new": # Liczymy commity z push events push_data = event.get("push_data") or {} commit_count = push_data.get("commit_count", 1) stats.commits += max(commit_count, 1) elif action in ("accepted", "merged"): stats.merge_requests += 1 elif action == "commented on": stats.comments += 1 else: stats.other += 1 def get_stats(self) -> list[UserStats]: """Zwraca listę statystyk posortowaną malejąco po contributions.""" return sorted( self._stats.values(), key=lambda s: s.total_contributions, reverse=True, )