Skip to content

Latest commit

 

History

History
356 lines (267 loc) · 17.1 KB

File metadata and controls

356 lines (267 loc) · 17.1 KB

banner

Grafos TP1 — Análise de Grafos com Dados do GitHub

Trabalho prático de Teoria dos Grafos (PUC Minas) que extrai eventos, comentários e reviews do repositório LadybirdBrowser/ladybird e os modela como redes de colaboração — com extração via API do GitHub em Python e construção, análise e exportação dos grafos em Java.


🛠️ Stack Principal

Java Maven Python Jupyter NetworkX Pandas GitHub API Gephi


📑 Sumário


📖 Sobre o projeto

Este projeto modela as interações de colaboração do repositório LadybirdBrowser/ladybird — um navegador open source com mais de 54 mil estrelas e milhares de pull requests, issues e reviews — como redes de grafos direcionados e ponderados. A pipeline é dividida em duas etapas:

  1. Extração (Python): coleta issues, pull requests, comentários, reviews e eventos via API REST do GitHub, com paginação automática, controle de rate limit e extração paralela (threads), salvando tudo em CSV.
  2. Análise (Java): carrega os CSVs, constrói diferentes tipos de grafos (lista ou matriz de adjacência), calcula métricas de centralidade, estrutura e comunidades, e exporta os resultados em formato GEXF para visualização no Gephi.

Notebooks Jupyter complementares (app/*.ipynb) replicam parte da modelagem em Python com NetworkX/Pandas, usados para exploração e validação cruzada dos grafos construídos em Java.


🏛️ Arquitetura

┌──────────────────────────────────────────────────────────────┐
│                     Extração (Python)                        │
│   GitHub REST API  →  core/api.py (paginação, rate limit,    │
│   threads)  →  issues.py / prs.py / comments.py  →  CSV      │
└────────────────────────────┬─────────────────────────────────┘
                             │  app/data/*.csv
┌────────────────────────────▼─────────────────────────────────┐
│                       Análise (Java)                         │
│  loader/  → carrega e mapeia os CSVs (GerenciadorUnificado)  │
│  builder/ → constrói os 4 tipos de grafo (GerenciadorGrafos) │
│  model/   → AbstractGraph (Lista ou Matriz de Adjacência)    │
│  service/ → métricas de centralidade, estrutura e comunidade │
│  ui/      → menu interativo de análise e exportação          │
└────────────────────────────┬─────────────────────────────────┘
                             │  app/exports/*.gexf
                      Visualização no Gephi

Padrões centrais:

Padrão Onde se aplica
Strategy / Template Method AbstractGraph com implementações AdjacencyListGraph e AdjacencyMatrixGraph
Builder especializado por tipo de grafo ConstrutorGrafo* coordenados pela fachada GerenciadorGrafos
Acúmulo de pesos por par de usuários ConstrutorGrafoIntegrado — combina todas as interações em arestas ponderadas
Algoritmo de Brandes Betweenness centrality (CentralityMetrics)
Label Propagation Detecção de comunidades (CommunityMetrics)
Rate limiting + retry com backoff exponencial Cliente da API do GitHub (core/api.py), thread-safe
Extração paralela ThreadPoolExecutor em prs.py (controlado por MAX_THREADS)

📁 Estrutura de pastas

grafos-tp1/
├── app/
│   ├── data/                              # CSVs extraídos do GitHub
│   │   ├── issue_authors.csv              # Autores das issues
│   │   ├── closed_issues.csv              # Issues fechadas
│   │   ├── issue_comments.csv             # Comentários em issues
│   │   ├── issue_events.csv               # Eventos de issues (closed, labeled...)
│   │   ├── pr_events.csv                  # Eventos de PRs (abertura, merge, fechamento)
│   │   ├── pr_reviews.csv                 # Reviews de pull requests
│   │   └── pr_comments.csv                # Comentários em PRs
│   │
│   ├── extraction/                        # Scripts Python de extração
│   │   ├── core/
│   │   │   ├── api.py                     # Cliente HTTP da API GitHub (rate limit, retries, threads)
│   │   │   └── io.py                      # Persistência em CSV
│   │   ├── comments.py                    # Extração de comentários
│   │   ├── issues.py                      # Extração de issues e seus eventos
│   │   ├── prs.py                         # Extração de PRs, reviews e eventos (paralela)
│   │   ├── extract_pr_events_quick.py     # Extração rápida só de eventos de PR
│   │   ├── check_rate_limit.py            # Verifica o rate limit atual da API
│   │   └── main.py                        # Menu principal de extração
│   │
│   ├── exports/                           # Grafos exportados em GEXF (Gephi)
│   │   ├── grafo_comentarios.gexf
│   │   ├── grafo_fechamentoissues.gexf
│   │   ├── grafo_pullrequests.gexf
│   │   └── grafo_grafointegrado.gexf
│   │
│   ├── graph.ipynb                        # Modelagem exploratória dos 3 grafos base (NetworkX)
│   ├── complete_graph.ipynb               # Modelagem do grafo integrado ponderado + métricas
│   ├── analysis.ipynb                     # Análise e visualização dos grafos extraídos
│   │
│   └── api/                               # Aplicação Java (Maven)
│       ├── pom.xml
│       └── src/main/java/com/grafos/puc/
│           ├── Main.java                  # Ponto de entrada — carrega dados e inicia o menu
│           ├── loader/                    # Leitura e mapeamento dos CSVs
│           │   ├── GerenciadorUnificado.java
│           │   ├── issues/                # Issue, GerenciadorIssues, ProcessadorIssuesGenerico
│           │   ├── pullRequest/           # PullRequest, Review, GerenciadorPullRequests...
│           │   └── comentarios/           # ItemComComentarios, processadores de comentários
│           ├── builder/                   # Construtores dos 4 tipos de grafo
│           │   ├── GerenciadorGrafos.java
│           │   ├── ConstrutorGrafoAbstrato.java
│           │   ├── ConstrutorGrafoComentarios.java
│           │   ├── ConstrutorGrafoFechamentoIssues.java
│           │   ├── ConstrutorGrafoReviewPullRequests.java
│           │   └── ConstrutorGrafoIntegrado.java
│           ├── model/                     # Representações de grafo direcionado
│           │   ├── AbstractGraph.java
│           │   ├── AdjacencyListGraph.java
│           │   └── AdjacencyMatrixGraph.java
│           ├── service/                   # Cálculo de métricas
│           │   ├── GraphMetricsService.java
│           │   └── metrics/               # CentralityMetrics, StructureMetrics, CommunityMetrics
│           └── ui/                        # Menus interativos de análise e exportação
│               ├── GerenciadorMenu.java
│               └── AnaliseGrafo.java
├── docs/                                  # Documentação e relatórios do TP1
│   ├── LadybirdBrowser.md
│   ├── enunciado-tp1.pdf
│   ├── relatorio-tp1.pdf
│   └── apresentacao.pdf
├── images/                                # Banners usados neste README
├── .env                                   # GITHUB_TOKEN (nunca versionar)
├── LICENSE
└── README.md

📊 Dados extraídos

Os dados são coletados do repositório LadybirdBrowser/ladybird e persistidos em app/data/ no formato CSV:

Arquivo Conteúdo Linhas (aprox.)
issue_authors.csv Autor, data e título de cada issue criada ~1.300
closed_issues.csv Quem fechou cada issue e quando ~750
issue_comments.csv Comentários em issues (ator, corpo, data, URL) ~27.600
issue_events.csv Eventos de issues — closed, labeled, etc. ~5.000
pr_events.csv Eventos de PR — abertura, fechamento, merge, merged_by ~5.700
pr_reviews.csv Reviews de PR (ator, estado, corpo) ~11.000
pr_comments.csv Comentários em pull requests ~22.700

O cliente da API (core/api.py) trata paginação automática, monitora os headers X-RateLimit-*, aguarda o reset quando o limite se esgota e faz retry com backoff exponencial em falhas transitórias — tudo de forma thread-safe para suportar a extração paralela de PRs (MAX_THREADS).


🕸️ Tipos de grafos gerados

A aplicação Java constrói 4 grafos direcionados, na seguinte ordem:

1️⃣ Grafo de Comentários Unificado

Quem comenta em issues e PRs, conectado a quem abriu o item.

Une comentários de issues e de pull requests em um único grafo: aresta comentarista → autor do item. Construído por ConstrutorGrafoComentarios.

2️⃣ Grafo de Fechamento de Issues

Quem fecha issues abertas por outras pessoas.

Cruza issue_authors.csv com closed_issues.csv: aresta quem fechou → quem criou a issue. Construído por ConstrutorGrafoFechamentoIssues.

3️⃣ Grafo de Pull Requests (Reviews)

Quem revisa o código de quem.

Modela o processo de revisão por pares: aresta revisor → autor do PR. Construído por ConstrutorGrafoReviewPullRequests.

4️⃣ Grafo Integrado Ponderado

Todas as interações combinadas em uma única rede, com pesos acumulados por par de usuários.

Soma, para cada par (origem, destino), o peso de todas as interações registradas entre eles:

Interação Peso
Comentário em issue 3.0
Comentário em PR 2.0
Review de PR 4.0
Merge de PR 5.0

Construído por ConstrutorGrafoIntegrado, que mantém um mapa (origem→destino) → peso acumulado antes de gerar as arestas finais — útil para identificar os colaboradores mais influentes na rede como um todo.

Os notebooks graph.ipynb e complete_graph.ipynb reproduzem a mesma modelagem em Python/NetworkX, servindo como conferência cruzada dos grafos construídos em Java.


📐 Métricas de análise

Implementadas em service/metrics/ e expostas via GraphMetricsService e o menu de análise (AnaliseGrafo):

Categoria Métricas Classe
Centralidade Degree, In-degree, Out-degree, Betweenness (Brandes), Closeness, PageRank CentralityMetrics
Estrutura e Coesão Densidade, Coeficiente de clustering, Assortatividade, Diâmetro StructureMetrics
Comunidades Detecção via Label Propagation, Modularidade (grafos direcionados/ponderados), Bridging ties CommunityMetrics

O menu de análise (GerenciadorMenuAnaliseGrafo) permite, para qualquer grafo carregado:

  1. Ver estatísticas básicas (vértices, arestas, densidade)
  2. Rankear vértices por grau
  3. Inspecionar propriedades estruturais
  4. Calcular métricas de centralidade
  5. Calcular métricas de estrutura avançadas
  6. Detectar comunidades
  7. Gerar um relatório completo com todas as métricas

Há ainda uma comparação lado a lado entre todos os grafos carregados (vértices ativos, arestas e densidade).


🚀 Como usar

Pré-requisitos

  • Java 21 (compilação e execução via Maven)
  • Python 3.x com requests e python-dotenv (e pandas, networkx, matplotlib, jupyter para os notebooks)
  • Token do GitHub válido, em um arquivo .env na raiz do projeto
  • Maven instalado

Instalação

# 1. Clone o repositório
git clone <url-do-repositorio>
cd grafos-tp1

# 2. Instale as dependências Python
pip install requests python-dotenv pandas networkx matplotlib jupyter

# 3. Configure o token do GitHub
echo "GITHUB_TOKEN=seu_token_aqui" > .env

# 4. Compile o projeto Java
mvn clean compile -f app/api/pom.xml

1. Extração de dados

python app/extraction/main.py

Menu interativo com as opções: coletar issues, coletar pull requests, coletar eventos de issues, coletar apenas eventos de PR, coletar tudo. Os CSVs são salvos em app/data/.

# Verificar o rate limit atual da API antes de uma extração longa
python app/extraction/check_rate_limit.py

2. Análise com Java

mvn exec:java -Dexec.mainClass="com.grafos.puc.Main" -f app/api/pom.xml

Ao iniciar, a aplicação carrega os CSVs de app/data/, pede para escolher entre Lista de Adjacência (grafos esparsos, menor uso de memória) ou Matriz de Adjacência (grafos densos, acesso mais rápido às arestas), constrói os 4 grafos na ordem descrita acima e abre o menu interativo de análise.

Build e testes

# Compilar
mvn clean compile -f app/api/pom.xml

# Executar testes
mvn test -f app/api/pom.xml

📤 Exportação para Gephi

Pelo menu da aplicação Java (opção 4. Exportar grafo para GEPHI), qualquer grafo carregado pode ser salvo em formato GEXF dentro de app/exports/, pronto para importação e visualização no Gephi:

  • grafo_comentarios.gexf
  • grafo_fechamentoissues.gexf
  • grafo_pullrequests.gexf
  • grafo_grafointegrado.gexf

A exportação é implementada diretamente em AdjacencyListGraph/AdjacencyMatrixGraph (exportToGEPHI), gerando um XML compatível com a especificação GEXF 1.2 — incluindo rótulos, pesos de vértices e de arestas.


📚 Documentação

Na pasta docs/ você encontra:

  • LadybirdBrowser.md — análise do repositório LadybirdBrowser/ladybird que justifica sua escolha como base de dados (popularidade, volume de interações, estrutura de colaboradores)
  • enunciado-tp1.pdf — enunciado do trabalho prático, com requisitos e critérios de avaliação
  • relatorio-tp1.pdf — relatório final com a análise dos resultados e discussão das métricas
  • apresentacao.pdf — slides usados na apresentação/vídeo do trabalho

📦 Tecnologias e dependências

Categoria Tecnologia
Linguagem (análise) Java 21
Build Maven 3.9+
Linguagem (extração) Python 3.x
HTTP / variáveis de ambiente requests, python-dotenv
Análise e modelagem de grafos networkx, pandas, matplotlib
Notebooks Jupyter
API de dados GitHub REST API v3
Visualização de grafos Gephi (via exportação GEXF)
Formato de dados CSV

⚠️ Observações importantes

  • Todos os comandos devem ser executados a partir do diretório raiz do projeto
  • O token do GitHub (GITHUB_TOKEN) é obrigatório para a extração de dados — nunca versione o .env
  • Os arquivos CSV precisam estar em app/data/ para a aplicação Java carregar os grafos
  • A aplicação suporta tanto grafos esparsos (lista de adjacência) quanto densos (matriz de adjacência)
  • MAX_THREADS controla o paralelismo da extração de PRs — reduza caso o rate limit se esgote rapidamente

Licença

Este projeto está sob a licença MIT. Veja o arquivo LICENSE para mais detalhes.


banner

Fonte do banner: João Paulo Carneiro Aramuni