diff --git a/.gitignore b/.gitignore
index 505a3b1..f6194c9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,12 @@ wheels/
# Virtual environments
.venv
+
+# Cache de análise de sentimento
+cache/
+*.cache
+
+# 🆕 Relatórios exportados
+exports/
+*.csv
+*.pdf
diff --git a/=3.8.0 b/=3.8.0
new file mode 100644
index 0000000..e69de29
diff --git a/README_files/DASHBOARD_ANALYTICS.md b/README_files/DASHBOARD_ANALYTICS.md
new file mode 100644
index 0000000..fb8562d
--- /dev/null
+++ b/README_files/DASHBOARD_ANALYTICS.md
@@ -0,0 +1,148 @@
+# 📊 Dashboard de Análise - PING UFF ANALYTICS
+
+## 🎯 Visão Geral
+
+O **Dashboard de Análise** é uma nova aba do PING que permite visualizar métricas agregadas dos dados raspados (posts e notícias) com filtros temporais e por fonte.
+
+---
+
+## ✨ Funcionalidades
+
+### 📈 Métricas Principais
+
+**Cards de Resumo:**
+- 📝 **Total de Registros**: Posts + notícias no período
+- ❤️ **Engajamento Total**: Soma de curtidas + comentários
+- 👍 **Média de Curtidas**: Por post
+- 💬 **Média de Comentários**: Por post
+
+**Gráficos e Análises:**
+- 📊 **Engajamento por Fonte**: Barras comparativas entre perfis
+- 🎯 **Distribuição por Perfil**: Posts e engajamento
+- 🏆 **Top 5 Posts**: Maior engajamento no período
+- 📰 **Notícias**: Total e distribuição por publisher
+
+---
+
+## 🎛️ Filtros Disponíveis
+
+### 📅 Filtro de Período
+
+**Campo Manual:**
+- Data Inicial (YYYY-MM-DD)
+- Data Final (YYYY-MM-DD)
+
+**Períodos Rápidos:**
+- ⚡ Últimos 7 dias
+- ⚡ Últimos 30 dias
+- ⚡ Últimos 90 dias
+- ⚡ Tudo (sem limite)
+
+### 📊 Filtro de Fontes
+
+Selecione uma ou mais fontes:
+- ☑️ @dceuff
+- ☑️ @reitor
+- ☑️ @vicereitor
+- ☑️ @noticias (notícias)
+
+---
+
+## 🔄 Como Usar
+
+1. **Acesse a aba "Dashboard"** no menu principal
+2. **Selecione o período** usando campos manuais ou botões rápidos
+3. **Selecione as fontes** desejadas (padrão: todas)
+4. **Clique em "Atualizar Dashboard"** para aplicar os filtros
+5. **Visualize as métricas** nos cards e gráficos
+
+---
+
+## 📊 Exemplos de Análise
+
+### Análise Mensal
+```
+Período: Últimos 30 dias
+Fontes: Todas
+
+Resultado:
+- Total: 245 registros
+- Engajamento: 15.340
+- Média curtidas: 52.3
+- Top post: @dceuff com 823 interações
+```
+
+### Comparação entre Fontes
+```
+Período: Últimos 90 dias
+Fontes: @dceuff, @reitor
+
+Resultado:
+- @dceuff: 450 posts, 28.500 engajamento
+- @reitor: 120 posts, 8.200 engajamento
+- DCE tem 3.75x mais posts
+```
+
+### Análise Anual
+```
+Período: 2024-01-01 a 2024-12-31
+Fontes: Todas
+
+Resultado:
+- Total: 2.413 registros
+- Engajamento total: 145.000
+- Post mais engajado: 1.234 interações
+- 100 notícias de 5 publishers
+```
+
+---
+
+## 🔧 Arquivos Relacionados
+
+- **[`analytics_dashboard.py`](../analytics_dashboard.py)** - Lógica de análise
+- **[`dashboard_visualizer.py`](../dashboard_visualizer.py)** - Geração de HTML
+- **[`app.py`](../app.py)** - Integração na interface
+
+---
+
+## 🎨 Estilo Visual
+
+O dashboard usa as mesmas **variáveis CSS** do resto da aplicação:
+- ✅ Compatível com light/dark mode
+- ✅ Gradientes nos cards
+- ✅ Gráficos de barras CSS puro
+- ✅ Responsivo
+
+---
+
+## 🚀 Futuras Melhorias
+
+### Em Desenvolvimento
+- [ ] Análise de sentimento em lote
+- [ ] Word cloud de tópicos
+- [ ] Gráficos de linha temporal
+- [ ] Exportação de relatórios (PDF/CSV)
+
+### Planejadas
+- [ ] Comparação entre períodos
+- [ ] Detecção de trending topics
+- [ ] Heatmap de postagens
+- [ ] Previsão de engajamento
+
+---
+
+## 📝 Changelog
+
+### v3.0 (Dezembro 2025)
+- ✅ Dashboard de análise inicial
+- ✅ Filtros de período e fontes
+- ✅ Métricas agregadas
+- ✅ Top posts
+- ✅ Distribuição por perfil
+- ✅ Seção de notícias
+
+---
+
+**Data**: 27 de Janeiro de 2025
+**Versão**: 3.0
+**Desenvolvido com ❤️ para a comunidade UFF**
\ No newline at end of file
diff --git a/README_files/analise_sentimento.md b/README_files/analise_sentimento.md
new file mode 100644
index 0000000..d6831f5
--- /dev/null
+++ b/README_files/analise_sentimento.md
@@ -0,0 +1,316 @@
+# 🎭 Análise de Sentimento - PING UFF ANALYTICS
+
+## 📊 Visão Geral
+
+A análise de sentimento do PING agora utiliza **Inteligência Artificial** para analisar o tom e percepção dos posts e **seus comentários**.
+
+## 🆕 Novidades (v3.3)
+
+### 1. **Filtro de Conteúdo** ⭐ NOVO
+- ✅ **Legendas + Comentários** - Análise completa (padrão)
+- ✅ **Apenas Legendas** - Sentimento do autor do post
+- ✅ **Apenas Comentários** - Sentimento da comunidade
+- ✅ **Cache separado** por tipo de conteúdo
+
+### 2. **Sistema de Cache Inteligente**
+- ✅ Cache automático de análises de sentimento
+- ✅ Invalidação inteligente - recalcula apenas quando necessário
+- ✅ Detecta automaticamente quando novos posts são adicionados
+- ✅ Economiza **5-10 minutos** em análises repetidas
+- ✅ Persistente em disco (JSON)
+
+### 3. **Análise de Comentários**
+- ✅ Analisa tanto **legendas** quanto **comentários dos usuários**
+- ✅ Considera o tom geral da conversa
+- ✅ Detecta divergências entre legenda e comentários
+
+### 4. **Sem Limite de Amostra**
+- ✅ Analisa **TODOS** os posts disponíveis
+- ✅ Não há mais limite de 100 posts
+- ✅ Respeita filtros de período e perfil
+
+### 5. **Dois Modos de Análise**
+
+#### 🤖 Modo IA Avançada (Recomendado)
+- Usa DeepSeek Chat ou Ollama Qwen3:30b
+- Análise contextual e precisa
+- Entende ironia, sarcasmo, nuances
+- Processa em lotes de 50 posts
+- **Tempo**: ~5-10min para 1000 posts (primeira vez)
+- **Cache**: ~1s para análises repetidas ⚡
+
+#### ⚡ Modo Palavras-chave (Rápido)
+- Análise básica por lista de palavras
+- Não entende contexto
+- Ideal para visualização rápida
+- **Tempo**: ~1-2s para 1000 posts
+- Não usa cache (muito rápido)
+
+## 🎯 Como Usar
+
+### 1. Na Interface Web
+
+**Aba 📊 Estatísticas:**
+```
+1. Selecione o perfil (ou "Todos")
+2. Escolha o modo:
+ - 🤖 IA Avançada
+ - ⚡ Palavras-chave
+3. Escolha o conteúdo: 🆕
+ - 📝 Legendas + Comentários (padrão)
+ - 🏷️ Apenas Legendas
+ - 💬 Apenas Comentários
+4. Clique em "🔄 Atualizar Sentimento" (usa cache)
+
+ OU
+
+ Clique em "🔥 Forçar Recálculo" (ignora cache)
+```
+
+**Gerenciar Cache:**
+- **Limpar Cache:** Botão "🗑️ Limpar Cache" remove todas as análises salvas
+- **Ver Estatísticas:** Painel "💾 Estatísticas do Cache" mostra uso
+- **Indicador:** 💾 = cache, 🆕 = análise nova
+
+### 2. Via Código
+
+```python
+from analytics_dashboard import DashboardAnalytics
+from embedding_manager import EmbeddingManager
+
+em = EmbeddingManager()
+analytics = DashboardAnalytics(em)
+
+# Análise completa (legendas + comentários)
+sentiment = analytics.get_sentiment_by_profile(
+ profile="dceuff",
+ use_llm=True,
+ use_cache=True,
+ content_filter="both", # 🆕 Padrão
+ limit=None
+)
+
+# Analisar apenas legendas (percepção do autor)
+sentiment = analytics.get_sentiment_by_profile(
+ profile="dceuff",
+ use_llm=True,
+ content_filter="caption" # 🆕 Apenas legendas
+)
+
+# Analisar apenas comentários (percepção da comunidade)
+sentiment = analytics.get_sentiment_by_profile(
+ profile="dceuff",
+ use_llm=True,
+ content_filter="comments" # 🆕 Apenas comentários
+)
+
+# Ver estatísticas do cache
+cache_stats = analytics.get_cache_stats()
+print(cache_stats)
+
+# Invalidar cache de um perfil e tipo de conteúdo
+analytics.invalidate_cache(
+ profile="dceuff",
+ content_filter="caption" # 🆕 Especificar tipo
+)
+
+# Limpar todo o cache
+analytics.cache.clear_all()
+```
+
+## 💡 Casos de Uso
+
+### 1. **Análise Completa (Padrão)**
+```python
+content_filter="both"
+```
+- Analisa legenda + comentários
+- Visão geral do sentimento
+- Detecta divergências
+
+### 2. **Sentimento do Autor**
+```python
+content_filter="caption"
+```
+- Apenas o que o perfil postou
+- Tom oficial da comunicação
+- Posicionamento institucional
+
+### 3. **Sentimento da Comunidade**
+```python
+content_filter="comments"
+```
+- Reação dos seguidores
+- Feedback do público
+- Percepção externa
+
+## 📊 Exemplo de Resultado
+
+```json
+{
+ "total_analyzed": 2437,
+ "positive": 856,
+ "negative": 1024,
+ "neutral": 557,
+ "positive_pct": 35.1,
+ "negative_pct": 42.0,
+ "neutral_pct": 22.9,
+ "trend": "negative",
+ "profiles": ["dceuff"],
+ "note": "Análise usando IA (modelo: DEEPSEEK) - 2437 registros completos",
+ "cached": true,
+ "content_filter": "both"
+}
+```
+
+## ⚙️ Configuração
+
+**Arquivo: `config.py`**
+```python
+# Modo padrão
+DEFAULT_SENTIMENT_MODE = 'llm' # ou 'keywords'
+
+# Tamanho do batch
+SENTIMENT_BATCH_SIZE = 50
+
+# Timeout
+SENTIMENT_TIMEOUT = 300 # 5 min
+```
+
+## 🔍 Estrutura de Dados
+
+### Posts com Comentários
+```json
+{
+ "text": "Perfil: dceuff\nData: 2024-10-15\n\n=== LEGENDA ===\nParabéns!\n\n=== COMENTÁRIOS ===\nQue ótimo!\nFinalmente!",
+ "profile": "dceuff",
+ "caption": "Parabéns!",
+ "comments_text": "Que ótimo!\nFinalmente!",
+ "likesCount": 250,
+ "commentsCount": 45
+}
+```
+
+### Cache (arquivo: `./cache/sentiment_cache.json`)
+```json
+{
+ "abc123def456": {
+ "result": { /* análise de sentimento */ },
+ "profile": "dceuff",
+ "start_date": null,
+ "end_date": null,
+ "total_docs": 1503,
+ "content_filter": "both",
+ "cached_at": "2025-10-27T14:30:00"
+ }
+}
+```
+
+## 📈 Performance
+
+| Modo | Posts | Conteúdo | Tempo (1ª vez) | Tempo (cache) | Precisão |
+|------|-------|----------|----------------|---------------|----------|
+| 🤖 IA | 1000 | Both | ~8min | ~0.5s ⚡ | ⭐⭐⭐⭐⭐ |
+| 🤖 IA | 1000 | Caption | ~5min | ~0.3s ⚡ | ⭐⭐⭐⭐⭐ |
+| 🤖 IA | 1000 | Comments | ~6min | ~0.4s ⚡ | ⭐⭐⭐⭐⭐ |
+| ⚡ Keywords | 1000 | Both | ~1s | ~1s | ⭐⭐⭐ |
+
+> **Cache acelera análises IA em ~500-1000x! 🚀**
+
+## 💾 Sistema de Cache
+
+### Como Funciona
+
+1. **Chave única:** Gerada a partir de:
+ - Perfil
+ - Data inicial
+ - Data final
+ - Total de documentos
+ - **Tipo de conteúdo** 🆕
+
+2. **Invalidação automática:**
+ - Novos posts adicionados → cache invalidado
+ - Total de documentos mudou → recalcula
+ - Tipo de conteúdo diferente → cache separado
+ - Mesmos parâmetros + mesmo total → usa cache
+
+3. **Persistência:**
+ - Salvo em `./cache/sentiment_cache.json`
+ - Metadados em `./cache/cache_metadata.json`
+ - Sobrevive a reinicializações
+
+### Quando o Cache é Usado
+
+✅ **USA CACHE:**
+- Modo IA Avançada
+- Mesmos filtros (perfil, datas, **tipo de conteúdo** 🆕)
+- Nenhum post novo adicionado
+
+❌ **NÃO USA CACHE:**
+- Modo Palavras-chave (muito rápido)
+- Total de posts mudou
+- Tipo de conteúdo diferente 🆕
+- `use_cache=False` explícito
+- Cache limpo manualmente
+
+## 🚨 Troubleshooting
+
+### Análise muito lenta
+```python
+# Use modo keywords para visualização rápida
+sentiment = analytics.get_sentiment_by_profile(
+ profile="dceuff",
+ use_llm=False
+)
+```
+
+### Cache desatualizado
+```python
+# Force recálculo
+sentiment = analytics.get_sentiment_by_profile(
+ profile="dceuff",
+ use_cache=False
+)
+
+# Ou limpe o cache
+analytics.cache.clear_all()
+```
+
+### Sem comentários nos posts
+```python
+# Analise apenas legendas
+sentiment = analytics.get_sentiment_by_profile(
+ profile="dceuff",
+ content_filter="caption" # 🆕 Ignora comentários
+)
+```
+
+### Erro de timeout
+```python
+# Em config.py, aumente o timeout
+SENTIMENT_TIMEOUT = 600 # 10 minutos
+```
+
+### Cache corrompido
+```bash
+# Limpe manualmente
+rm -rf ./cache/
+```
+
+## 🔮 Próximas Melhorias
+
+- [x] Cache de análises (evitar recalcular) ✅
+- [x] Filtro de conteúdo (legenda/comentários) ✅
+- [ ] Análise de hashtags e menções
+- [ ] Detecção de tópicos emergentes
+- [ ] Comparação de sentimento entre períodos
+- [ ] Exportação de relatórios
+- [ ] TTL (Time-To-Live) para cache
+- [ ] Compressão do cache
+- [ ] Análise de divergência legenda vs. comentários
+
+---
+
+**Versão**: 3.3
+**Data**: 27 de Outubro de 2025
+**Status**: ✅ Produção
diff --git a/agent_system.py b/agent_system.py
index f14d23a..d53dd0a 100644
--- a/agent_system.py
+++ b/agent_system.py
@@ -136,13 +136,20 @@ def _create_tools_description(self) -> str:
- Retorna: Contagem positivo/negativo/neutro, aspectos positivos/negativos, resumo qualitativo
11. **semantic_search**
- - Uso: Buscar posts/notícias por CONTEÚDO/TEMA usando busca semântica vetorial
- - Quando usar: Perguntas sobre "o que foi dito", "posts sobre X", "aparições", "mencionou", etc.
- - Parâmetros: query (str - reformule para otimizar busca), n_results (int), profile (str, opcional), content_type_filter (str, opcional: 'news' ou 'instagram_post')
+ - Uso: Buscar posts/notícias/DEBATES por CONTEÚDO/TEMA usando busca semântica vetorial
+ - Quando usar: Perguntas sobre "o que foi dito", "posts sobre X", "aparições", "mencionou", "posicionamento sobre Y", etc.
+ - Parâmetros:
+ * query (str - reformule para otimizar busca)
+ * n_results (int)
+ * profile (str, opcional)
+ * content_type_filter (str, opcional: 'news', 'instagram_post' ou 'debate')
- Exemplo: {"tool": "semantic_search", "params": {"query": "HUAP hospital atendimento saúde", "n_results": 8}}
- - Exemplo com filtro: {"tool": "semantic_search", "params": {"query": "cotas ações afirmativas", "n_results": 10, "content_type_filter": "news"}}
+ - Exemplo com filtro de notícias: {"tool": "semantic_search", "params": {"query": "cotas ações afirmativas", "n_results": 10, "content_type_filter": "news"}}
+ - Exemplo com filtro de debates: {"tool": "semantic_search", "params": {"query": "Roberto Salles teletrabalho 30 horas servidor", "n_results": 15, "content_type_filter": "debate"}}
- IMPORTANTE: Reformule a query do usuário para termos mais específicos e relevantes
- - IMPORTANTE: Use content_type_filter='news' quando buscar sobre ex-reitor ou período histórico
+ - IMPORTANTE: Use content_type_filter='news' quando buscar sobre ex-reitor ou período histórico (2009-2018)
+ - IMPORTANTE: Use content_type_filter='debate' quando buscar POSICIONAMENTO POLÍTICO, PROPOSTAS, ARGUMENTOS
+ - IMPORTANTE: A LLM LÊ O CAMPO "trecho" dos debates, que contém as FALAS LITERAIS de Roberto Salles
12. **get_news_articles**
- Uso: Buscar NOTÍCIAS filtradas por data e/ou publisher
@@ -177,14 +184,26 @@ def _create_tools_description(self) -> str:
- @vicereitor (Vice-Reitor ATUAL da UFF)
## FONTES DE DADOS AUXILIARES:
-- Notícias/Arquivo: Conteúdo histórico sobre a UFF e ex-reitor Roberto Salles (2009-2018)
+- **Notícias/Arquivo**: Conteúdo histórico sobre a UFF e ex-reitor Roberto Salles (2009-2018)
- Use para perguntas sobre Roberto Salles/Sales ou eventos passados
+ - Ferramentas: search_news_by_person, get_news_articles, semantic_search com content_type_filter='news'
+
+- **Debates Políticos**: Transcrições de debates eleitorais de Roberto Salles (período 2006-2018)
+ - Use para perguntas sobre POSICIONAMENTO POLÍTICO, PROPOSTAS DE CAMPANHA, DEBATES ELEITORAIS
+ - Contém argumentos, propostas e posições políticas detalhadas no campo "trecho" (falas literais)
+ - Ferramenta: semantic_search com content_type_filter='debate'
+ - Palavras-chave: "debate", "eleição", "proposta", "plano de governo", "candidatura", "posicionamento"
+ - CAMPOS IMPORTANTES:
+ * "trecho": contém a FALA LITERAL de Roberto Salles (ex: "XXX_Roberto SallesNós vamos retornar as 30 horas...")
+ * "topicos": temas abordados (ex: "30h/Teletrabalho", "Hospital/EBSERH", "ReUni/Infra")
+ * "fonte": qual debate (1o_debate, 2o_debate, etc.)
+ * "timecode": momento da fala no debate
## CONTEXTO IMPORTANTE:
- **Roberto Salles (ou Roberto Sales)** foi REITOR DA UFF entre 2009-2018
- Notícias sobre "reitor da UFF" do período 2009-2018 referem-se a Roberto Salles
- Posts atuais (2023-2025) do perfil @reitor referem-se ao REITOR ATUAL (Antônio Cláudio Nóbrega)
-- Para perguntas sobre Roberto Salles: SEMPRE buscar em NOTÍCIAS, nunca em posts atuais
+- Para perguntas sobre Roberto Salles: SEMPRE buscar em NOTÍCIAS ou DEBATES, nunca em posts atuais
## DIRETRIZES CRÍTICAS:
@@ -204,6 +223,20 @@ def _create_tools_description(self) -> str:
✅ Exemplos: "o que Roberto Salles achava de X", "posição do ex-reitor sobre Y", "Roberto Salles falou sobre Z"
✅ GATILHOS CRÍTICOS: "ex-reitor", "Roberto", "Salles", "Sales" → buscar em notícias (2009-2018)
+### 🆕 Use BUSCA EM DEBATES quando:
+✅ Pergunta sobre PROPOSTAS DE CAMPANHA: "o que Roberto Salles propôs", "plano de governo", "promessas de campanha"
+✅ Pergunta sobre DEBATES ELEITORAIS: "debate eleitoral", "discussão política", "confronto eleitoral"
+✅ Pergunta sobre POSICIONAMENTO POLÍTICO DETALHADO: "visão política de X", "ideologia", "argumentos defendidos"
+✅ Pergunta sobre FALAS ESPECÍFICAS: "o que Roberto Salles disse sobre X no debate", "posicionamento sobre Y"
+✅ IMPORTANTE: Para debates, use semantic_search COM content_type_filter='debate'
+✅ Exemplos:
+ - "qual o posicionamento de Roberto Salles sobre teletrabalho?" → buscar em debates
+ - "o que Roberto Salles defendeu sobre as 30 horas?" → buscar em debates
+ - "propostas de Roberto Salles para educação" → buscar em debates
+ - "o que Roberto Salles disse sobre hospital/EBSERH?" → buscar em debates
+✅ COMBINE com notícias para contexto completo: debates (propostas) + notícias (implementação)
+✅ A LLM LEIA o campo "trecho" que contém as falas LITERAIS de Roberto Salles nos debates
+
### Use WEB_SEARCH quando:
✅ CONTEXTO EXTERNO/ATUALIZADO: "como está X em 2025", "últimas notícias sobre Y", "o que está acontecendo com Z"
✅ NOTÍCIAS RECENTES: "notícias de hoje", "eventos recentes", "informação atualizada"
@@ -223,12 +256,16 @@ def _create_tools_description(self) -> str:
### COMBINE FERRAMENTAS quando:
✅ Pergunta tem MÉTRICA + CONTEÚDO: use semantic_search primeiro, depois filtre por métrica
✅ Pergunta tem CONTEXTO EXTERNO + LOCAL: use web_search + semantic_search
+✅ Pergunta sobre ROBERTO SALLES (COMPLETA): debates (propostas) + notícias (ações) + semantic_search geral
✅ Precisa de CONTEXTO + RANKING: busca semântica + ordenação
## INSTRUÇÕES:
- Analise se a pergunta é sobre CONTEÚDO (use semantic_search), MÉTRICAS (use tools estruturadas) ou CONTEXTO EXTERNO (use web_search)
+- Para perguntas sobre Roberto Salles, SEMPRE considere usar MÚLTIPLAS fontes: debates + notícias
+- Para perguntas sobre POSICIONAMENTO/FALAS de Roberto Salles, PRIORIZE busca em debates com content_type_filter='debate'
- Você pode usar MÚLTIPLAS ferramentas em sequência
- Ao usar semantic_search, REFORMULE a query para termos mais específicos
+- A LLM deve LER o campo "trecho" dos debates que contém as falas literais
- Retorne APENAS um JSON válido, sem texto adicional
"""
@@ -271,8 +308,10 @@ def _plan_action(
- @vicereitor (Vice-Reitor ATUAL: Fábio Barbosa Passos)
**FONTES AUXILIARES (NÃO são perfis):**
-- Notícias/Arquivo: Para perguntas sobre ex-reitor Roberto Salles ou eventos históricos
- - Use ferramentas: search_news_by_person, get_news_articles, semantic_search com content_type_filter='news'
+- **Notícias/Arquivo**: Para perguntas sobre ex-reitor Roberto Salles ou eventos históricos (2009-2018)
+ - Ferramentas: search_news_by_person, get_news_articles, semantic_search com content_type_filter='news'
+- **Debates Políticos**: Para perguntas sobre propostas, argumentos e posicionamento político de Roberto Salles
+ - Ferramenta: semantic_search sem filtro ou genérico (busca em transcrições de debates)
## 📅 DATAS CRÍTICAS (NÃO CONFUNDA!):
- **Roberto de Souza Salles**: Reitor de **23 de novembro de 2006 até 18 de novembro de 2014**
@@ -418,10 +457,41 @@ def _plan_action(
]
}}
+🆕 Pergunta: "Quais eram as propostas de Roberto Salles para a educação?"
+{{
+ "reasoning": "Pergunta sobre PROPOSTAS DE CAMPANHA do ex-reitor. Deve buscar em DEBATES (propostas políticas) + NOTÍCIAS (implementação). Usar semantic_search genérico para debates e com filtro para notícias",
+ "actions": [
+ {{"tool": "semantic_search", "params": {{"query": "Roberto Salles educação ensino proposta plano universidade", "n_results": 15}}}},
+ {{"tool": "search_news_by_person", "params": {{"person_name": "Roberto Salles", "limit": 10}}}}
+ ]
+}}
+
+🆕 Pergunta: "O que Roberto Salles defendeu nos debates eleitorais?"
+{{
+ "reasoning": "Pergunta sobre DEBATES ELEITORAIS. Foco primário em transcrições de debates. Usar semantic_search genérico com termos relacionados a debates e propostas",
+ "actions": [
+ {{"tool": "semantic_search", "params": {{"query": "Roberto Salles debate eleitoral candidato propostas argumentos defende eleição", "n_results": 20}}}}
+ ]
+}}
+
+🆕 Pergunta: "Qual era a visão política de Roberto Salles sobre pesquisa científica?"
+{{
+ "reasoning": "Pergunta sobre POSICIONAMENTO POLÍTICO detalhado. Combinar debates (visão política) + notícias (ações). Usar múltiplas buscas semânticas",
+ "actions": [
+ {{"tool": "semantic_search", "params": {{"query": "Roberto Salles pesquisa científica ciência tecnologia inovação desenvolvimento", "n_results": 15}}}},
+ {{"tool": "search_news_by_person", "params": {{"person_name": "Roberto Salles", "limit": 10}}}},
+ {{"tool": "semantic_search", "params": {{"query": "pesquisa ciência universidade UFF política científica", "n_results": 10, "content_type_filter": "news"}}}}
+ ]
+}}
+
IMPORTANTE:
- Para CONTEÚDO/TEMA → semantic_search (sempre reformule query)
- Para MÉTRICAS/RANKING → ferramentas estruturadas
- Para CONTEXTO EXTERNO/ATUALIZADO → web_search (notícias recentes, eventos atuais)
+- Para ROBERTO SALLES:
+ - PROPOSTAS/DEBATES → semantic_search genérico (debates)
+ - NOTÍCIAS/AÇÕES → search_news_by_person + semantic_search com content_type_filter='news'
+ - ANÁLISE COMPLETA → combine ambas as fontes
- DICAS para web_search: transforme perguntas como "qual é a situação de X?" em "X Brasil 2025" ou "X notícias recentes"
- Retorne APENAS o JSON, nada mais!
"""
@@ -978,26 +1048,38 @@ def _synthesize_response(
context += self._format_results_for_llm(results, tool_name)
context += "\n---\n\n"
- synthesis_prompt = f"""{context}
-
-## Pergunta Original do Usuário:
-{user_question}
-
-## Sua Tarefa:
-Sintetize os dados acima em uma resposta clara, completa e bem formatada para o usuário.
-
-DIRETRIZES:
-1. Use APENAS os dados fornecidos acima
-2. Seja objetivo e direto
-3. Cite números específicos e links quando relevante
-4. Use formatação markdown para melhor legibilidade
-5. Organize a informação de forma lógica
-6. Se múltiplas ferramentas foram usadas, integre os resultados de forma coerente
-7. Sempre inclua links dos posts quando disponível
-8. NÃO repita instruções ou seções de "Diretrizes" na sua resposta
-9. NÃO inclua avisos sobre Roberto Salles a menos que a pergunta mencione especificamente sobre ele
-
-NÃO invente informações que não estão no contexto!
+ # Atualiza o prompt de síntese com instruções críticas
+ synthesis_prompt = f"""Você é um assistente especializado da Universidade Federal Fluminense (UFF).
+
+Pergunta do usuário: "{user_question}"
+
+Dados recuperados:
+{context}
+
+## INSTRUÇÕES CRÍTICAS:
+
+1. **CITE AS FONTES CORRETAMENTE**:
+ - Para debates: "Segundo Roberto Salles no [fonte do debate], ele afirmou: '[trecho da fala]'"
+ - Para notícias: "De acordo com [publisher] em [data]..."
+ - Para posts: "Em post de @[profile] em [data]..."
+
+2. **USE AS FALAS LITERAIS DOS DEBATES**:
+ - O campo "trecho" contém as FALAS LITERAIS de Roberto Salles
+ - Cite textualmente quando relevante (ex: "Roberto Salles afirmou: 'Nós vamos retornar as 30 horas'")
+ - Identifique o contexto do debate (1o_debate, 2o_debate, etc.)
+
+3. **ESTRUTURE A RESPOSTA**:
+ - Responda diretamente à pergunta
+ - Use citações literais dos debates quando disponível
+ - Contextualize com informações de notícias se houver
+ - Seja preciso sobre datas e eventos
+
+4. **EVITE**:
+ - Inventar informações não presentes nos dados
+ - Misturar contextos temporais (ex: não confunda ações de 2009-2018 com 2023-2025)
+ - Atribuir falas de uma fonte a outra
+
+Responda em português brasileiro de forma clara e objetiva.
"""
try:
diff --git a/analytics_dashboard.py b/analytics_dashboard.py
new file mode 100644
index 0000000..56ecf8c
--- /dev/null
+++ b/analytics_dashboard.py
@@ -0,0 +1,960 @@
+"""
+Módulo para análises e métricas do dashboard.
+Processa dados de posts e notícias para visualização.
+"""
+
+from typing import Dict, List, Any, Optional, Tuple
+from datetime import datetime, timedelta, timezone
+from dateutil import parser as date_parser
+from embedding_manager import EmbeddingManager
+from query_tools import QueryTools
+from config import DEFAULT_PROVIDER, DEEPSEEK_MODEL
+import llm_chat
+import json
+from sentiment_cache import SentimentCache
+from report_exporter import ReportExporter
+
+
+class DashboardAnalytics:
+ """Gerenciador de análises para o dashboard."""
+
+ def __init__(self, embedding_manager: EmbeddingManager):
+ self.em = embedding_manager
+ self.tools = QueryTools(embedding_manager)
+ self.collection = embedding_manager.collection
+ self.cache = SentimentCache()
+ self.exporter = ReportExporter()
+
+ def _normalize_datetime(self, dt: datetime) -> datetime:
+ """
+ Normaliza datetime para ter timezone UTC.
+
+ Args:
+ dt: Datetime a normalizar
+
+ Returns:
+ Datetime com timezone UTC
+ """
+ if dt.tzinfo is None:
+ # Se não tem timezone, assume UTC
+ return dt.replace(tzinfo=timezone.utc)
+ else:
+ # Converte para UTC se tiver outro timezone
+ return dt.astimezone(timezone.utc)
+
+ def get_sentiment_by_profile(
+ self,
+ profile: str,
+ start_date: Optional[str] = None,
+ end_date: Optional[str] = None,
+ limit: int = None,
+ use_llm: bool = True,
+ use_cache: bool = True,
+ content_filter: str = "both" # 🆕 Filtro de conteúdo
+ ) -> Dict[str, Any]:
+ """
+ Analisa sentimento de um perfil específico.
+
+ Args:
+ profile: Nome do perfil (@dceuff, @reitor, @vicereitor)
+ start_date: Data inicial (ISO format ou None)
+ end_date: Data final (ISO format ou None)
+ limit: Máximo de posts a analisar (None = todos)
+ use_llm: Se True, usa IA avançada; False = palavras-chave
+ use_cache: Se True, usa cache (padrão: True)
+ content_filter: Tipo de conteúdo a analisar:
+ - "both": Legenda + Comentários (padrão)
+ - "caption": Apenas legendas
+ - "comments": Apenas comentários
+
+ Returns:
+ Dict com análise de sentimento do perfil
+ """
+ # 🆕 Trata profile=None (todos os perfis)
+ if profile is None:
+ where_clause = None
+ profile_clean = None
+ else:
+ profile_clean = profile.replace('@', '').lower()
+ where_clause = {'profile': profile_clean}
+
+ results = self.collection.get(
+ where=where_clause,
+ limit=100000,
+ include=['metadatas', 'documents']
+ )
+
+ if not results['ids']:
+ profile_display = f'@{profile_clean}' if profile_clean else 'todos os perfis'
+ return {
+ 'profile': profile_clean,
+ 'total_analyzed': 0,
+ 'positive': 0,
+ 'negative': 0,
+ 'neutral': 0,
+ 'positive_pct': 0,
+ 'negative_pct': 0,
+ 'neutral_pct': 0,
+ 'trend': 'neutral',
+ 'note': f'Nenhum registro encontrado para {profile_display}',
+ 'cached': False,
+ 'content_filter': content_filter
+ }
+
+ # Normaliza datas de filtro
+ start_filter = None
+ end_filter = None
+
+ if start_date:
+ try:
+ start_filter = self._normalize_datetime(date_parser.parse(start_date))
+ except Exception as e:
+ print(f"⚠️ Erro ao parsear start_date '{start_date}': {e}")
+
+ if end_date:
+ try:
+ end_filter = self._normalize_datetime(date_parser.parse(end_date))
+ except Exception as e:
+ print(f"⚠️ Erro ao parsear end_date '{end_date}': {e}")
+
+ # Filtra por data e coleta documentos
+ filtered_documents = []
+
+ for i, metadata in enumerate(results['metadatas']):
+ try:
+ if metadata.get('content_type') == 'news':
+ continue
+
+ post_date = date_parser.parse(metadata['timestamp'])
+ post_date = self._normalize_datetime(post_date)
+
+ if start_filter and post_date < start_filter:
+ continue
+
+ if end_filter and post_date > end_filter:
+ continue
+
+ if i < len(results['documents']):
+ # 🆕 Aplica filtro de conteúdo
+ full_text = results['documents'][i]
+ filtered_text = self._filter_content_by_type(full_text, metadata, content_filter)
+
+ # Só adiciona se houver conteúdo após filtragem
+ if filtered_text and filtered_text.strip():
+ filtered_documents.append({
+ 'text': filtered_text,
+ 'metadata': metadata
+ })
+
+ except Exception as e:
+ print(f"⚠️ Erro ao processar metadata: {e}")
+ continue
+
+ # Aplica limite apenas se especificado
+ if limit:
+ filtered_documents = filtered_documents[:limit]
+
+ total_docs = len(filtered_documents)
+
+ # 🆕 Verifica cache
+ if use_cache and use_llm:
+ cached_result = self.cache.get(
+ profile=profile_clean,
+ start_date=start_date,
+ end_date=end_date,
+ total_docs=total_docs,
+ content_filter=content_filter # 🆕 Passa filtro para cache
+ )
+
+ if cached_result:
+ cached_result['cached'] = True
+ cached_result['profile'] = profile_clean
+ cached_result['display_name'] = f"@{profile_clean}"
+ cached_result['content_filter'] = content_filter
+ return cached_result
+
+ # Análise nova (cache miss ou desabilitado)
+ sentiment_data = self._analyze_sentiment_batch(
+ filtered_documents,
+ [profile_clean] if profile_clean else None,
+ use_llm=use_llm
+ )
+
+ sentiment_data['profile'] = profile_clean
+ sentiment_data['display_name'] = f"@{profile_clean}" if profile_clean else "Todos os perfis"
+ sentiment_data['cached'] = False
+ sentiment_data['content_filter'] = content_filter
+
+ # 🆕 Salva no cache
+ if use_cache and use_llm:
+ self.cache.set(
+ sentiment_data,
+ profile=profile_clean,
+ start_date=start_date,
+ end_date=end_date,
+ total_docs=total_docs,
+ content_filter=content_filter # 🆕 Passa filtro para cache
+ )
+
+ return sentiment_data
+
+ def _filter_content_by_type(
+ self,
+ full_text: str,
+ metadata: Dict[str, Any],
+ content_filter: str
+ ) -> str:
+ """
+ 🆕 Filtra conteúdo do post baseado no tipo selecionado.
+
+ Args:
+ full_text: Texto completo do post (legenda + comentários)
+ metadata: Metadados do post
+ content_filter: Tipo de conteúdo ("both", "caption", "comments")
+
+ Returns:
+ Texto filtrado conforme seleção
+ """
+ if content_filter == "both":
+ return full_text
+
+ # 🔍 DEBUG: Vamos ver o que temos
+ print(f"\n🔍 DEBUG _filter_content_by_type:")
+ print(f" content_filter: {content_filter}")
+ print(f" metadata keys: {metadata.keys()}")
+ print(f" full_text preview: {full_text[:200]}...")
+
+ # Extrai apenas a legenda
+ if content_filter == "caption":
+ # Tenta pegar do metadata primeiro (mais confiável)
+ caption = metadata.get('caption', '')
+ if caption:
+ return f"Perfil: {metadata.get('profile', '')}\nData: {metadata.get('timestamp', '')}\n\nLegenda: {caption}"
+
+ # Fallback: parse do texto completo
+ if "=== LEGENDA ===" in full_text and "=== COMENTÁRIOS ===" in full_text:
+ parts = full_text.split("=== COMENTÁRIOS ===")
+ return parts[0].strip()
+ elif "=== LEGENDA ===" in full_text:
+ return full_text.strip()
+ else:
+ # Se não tem marcadores, considera tudo como legenda
+ return full_text
+
+ # Extrai apenas os comentários
+ if content_filter == "comments":
+ # Tenta pegar do metadata primeiro
+ comments_text = metadata.get('comments_text', '')
+ if comments_text:
+ print(f" ✅ Found comments_text in metadata: {len(comments_text)} chars")
+ return f"Perfil: {metadata.get('profile', '')}\nData: {metadata.get('timestamp', '')}\n\nComentários:\n{comments_text}"
+
+ # Fallback: parse do texto completo
+ if "=== COMENTÁRIOS ===" in full_text:
+ parts = full_text.split("=== COMENTÁRIOS ===")
+ if len(parts) > 1:
+ comments = parts[1].strip()
+ print(f" ✅ Parsed comments from text: {len(comments)} chars")
+ return f"Comentários:\n{comments}"
+
+ # 🆕 Tenta outro formato comum
+ if "\n\n---\n\nComentários:" in full_text:
+ parts = full_text.split("\n\n---\n\nComentários:")
+ if len(parts) > 1:
+ comments = parts[1].strip()
+ print(f" ✅ Parsed comments (alt format): {len(comments)} chars")
+ return f"Comentários:\n{comments}"
+
+ print(f" ⚠️ NO COMMENTS FOUND - returning empty")
+ return "" # Sem comentários
+
+ return full_text # Fallback
+
+ def _analyze_sentiment_batch(
+ self,
+ documents: List[Dict[str, Any]],
+ profiles: Optional[List[str]] = None,
+ use_llm: bool = True # 🆕 Usar LLM por padrão
+ ) -> Dict[str, Any]:
+ """
+ Analisa sentimento agregado de um conjunto de documentos.
+
+ Args:
+ documents: Lista de dicts com 'text' e 'metadata'
+ profiles: Lista de perfis filtrados
+ use_llm: Se True, usa LLM para análise mais precisa (padrão: True)
+
+ Returns:
+ Dict com análise de sentimento agregada
+ """
+ if not documents:
+ return {
+ 'total_analyzed': 0,
+ 'positive': 0,
+ 'negative': 0,
+ 'neutral': 0,
+ 'positive_pct': 0,
+ 'negative_pct': 0,
+ 'neutral_pct': 0,
+ 'trend': 'neutral',
+ 'profiles': profiles or [],
+ 'note': 'Nenhum registro para analisar'
+ }
+
+ total_docs = len(documents)
+ print(f"🎭 Analisando sentimento de {total_docs} registros...")
+
+ # 🆕 ANÁLISE COM LLM (mais precisa)
+ if use_llm:
+ return self._analyze_sentiment_with_llm(documents, profiles)
+
+ # 🔧 FALLBACK: Análise por palavras-chave (mais rápida)
+ return self._analyze_sentiment_with_keywords(documents, profiles)
+
+ def _analyze_sentiment_with_llm(
+ self,
+ documents: List[Dict[str, Any]],
+ profiles: Optional[List[str]] = None
+ ) -> Dict[str, Any]:
+ """
+ 🆕 Análise de sentimento usando LLM em batch.
+
+ Processa todos os documentos em lotes para análise precisa.
+ """
+ total_docs = len(documents)
+ batch_size = 50 # Processa 50 posts por vez
+
+ positive_count = 0
+ negative_count = 0
+ neutral_count = 0
+
+ # Processa em batches
+ for i in range(0, total_docs, batch_size):
+ batch = documents[i:i + batch_size]
+ batch_num = (i // batch_size) + 1
+ total_batches = (total_docs + batch_size - 1) // batch_size
+
+ print(f" 📦 Processando lote {batch_num}/{total_batches} ({len(batch)} posts)...")
+
+ # Prepara texto do batch
+ batch_text = "\n\n---POST---\n\n".join([
+ f"POST {j+1}:\n{doc['text'][:800]}" # Limita cada post a 800 chars
+ for j, doc in enumerate(batch)
+ ])
+
+ # Prompt para análise em batch
+ prompt = f"""Analise o sentimento de cada um dos {len(batch)} posts abaixo.
+
+INSTRUÇÕES:
+- Classifique cada post como: POSITIVO, NEGATIVO ou NEUTRO
+- Considere tanto a legenda quanto os comentários dos usuários
+- Analise o tom geral da conversa
+- Se houver divergência entre legenda e comentários, priorize o sentimento dominante
+
+POSTS:
+{batch_text}
+
+Retorne APENAS um JSON com o formato:
+{{
+ "sentiments": ["POSITIVO", "NEGATIVO", "NEUTRO", ...],
+ "reasoning": "Breve explicação da análise geral"
+}}
+
+A lista "sentiments" deve ter EXATAMENTE {len(batch)} elementos, um para cada post."""
+
+ try:
+ # Usa provider configurado (DeepSeek ou Ollama)
+ if DEFAULT_PROVIDER == 'deepseek':
+ model = DEEPSEEK_MODEL
+ else:
+ model = "qwen3:30b"
+
+ response = llm_chat.chat(
+ model=model,
+ messages=[{'role': 'user', 'content': prompt}]
+ )
+
+ response_text = response['message']['content']
+
+ # Parse JSON
+ if '```json' in response_text:
+ response_text = response_text.split('```json')[1].split('```')[0]
+ elif '```' in response_text:
+ response_text = response_text.split('```')[1].split('```')[0]
+
+ result = json.loads(response_text.strip())
+ sentiments = result.get('sentiments', [])
+
+ # Conta sentimentos
+ for s in sentiments:
+ s_upper = s.upper()
+ if 'POSITIV' in s_upper:
+ positive_count += 1
+ elif 'NEGATIV' in s_upper:
+ negative_count += 1
+ else:
+ neutral_count += 1
+
+ print(f" ✓ Lote analisado com sucesso")
+
+ except Exception as e:
+ print(f" ⚠️ Erro no lote {batch_num}: {e}")
+ # Fallback: marca todos como neutros
+ neutral_count += len(batch)
+
+ # Calcula percentuais
+ total = positive_count + negative_count + neutral_count
+ pos_pct = (positive_count / total * 100) if total > 0 else 0
+ neg_pct = (negative_count / total * 100) if total > 0 else 0
+ neu_pct = (neutral_count / total * 100) if total > 0 else 0
+
+ # Define tendência
+ if pos_pct > neg_pct and pos_pct > neu_pct:
+ trend = 'positive'
+ elif neg_pct > pos_pct and neg_pct > neu_pct:
+ trend = 'negative'
+ else:
+ trend = 'neutral'
+
+ return {
+ 'total_analyzed': total_docs,
+ 'positive': positive_count,
+ 'negative': negative_count,
+ 'neutral': neutral_count,
+ 'positive_pct': round(pos_pct, 1),
+ 'negative_pct': round(neg_pct, 1),
+ 'neutral_pct': round(neu_pct, 1),
+ 'trend': trend,
+ 'profiles': profiles or [],
+ 'note': f'Análise usando IA (modelo: {DEFAULT_PROVIDER.upper()}) - {total_docs} registros completos'
+ }
+
+ def _analyze_sentiment_with_keywords(
+ self,
+ documents: List[Dict[str, Any]],
+ profiles: Optional[List[str]] = None
+ ) -> Dict[str, Any]:
+ """
+ 🔧 FALLBACK: Análise simplificada por palavras-chave.
+ Usado quando LLM não está disponível ou para análises rápidas.
+ """
+ positive_keywords = [
+ 'parabéns', 'excelente', 'ótimo', 'maravilhoso', 'sucesso',
+ 'conquista', 'vitória', 'alegria', 'feliz', 'orgulho',
+ 'gratidão', 'obrigado', 'apoio', 'solidariedade', 'esperança',
+ 'incrível', 'fantástico', 'perfeito', 'adorei', 'amei'
+ ]
+
+ negative_keywords = [
+ 'problema', 'crítica', 'péssimo', 'ruim', 'revolta',
+ 'denúncia', 'descaso', 'abandono', 'precário', 'injustiça',
+ 'horrível', 'terrível', 'lamentável', 'triste', 'decepção'
+ ]
+
+ positive_count = 0
+ negative_count = 0
+ neutral_count = 0
+
+ for doc in documents:
+ text_lower = doc['text'].lower()
+
+ pos_score = sum(1 for kw in positive_keywords if kw in text_lower)
+ neg_score = sum(1 for kw in negative_keywords if kw in text_lower)
+
+ if pos_score > neg_score and pos_score > 0:
+ positive_count += 1
+ elif neg_score > pos_score and neg_score > 0:
+ negative_count += 1
+ else:
+ neutral_count += 1
+
+ total = len(documents)
+ pos_pct = (positive_count / total * 100) if total > 0 else 0
+ neg_pct = (negative_count / total * 100) if total > 0 else 0
+ neu_pct = (neutral_count / total * 100) if total > 0 else 0
+
+ if pos_pct > neg_pct and pos_pct > neu_pct:
+ trend = 'positive'
+ elif neg_pct > pos_pct and neg_pct > neu_pct:
+ trend = 'negative'
+ else:
+ trend = 'neutral'
+
+ return {
+ 'total_analyzed': total,
+ 'positive': positive_count,
+ 'negative': negative_count,
+ 'neutral': neutral_count,
+ 'positive_pct': round(pos_pct, 1),
+ 'negative_pct': round(neg_pct, 1),
+ 'neutral_pct': round(neu_pct, 1),
+ 'trend': trend,
+ 'profiles': profiles or [],
+ 'note': f'Análise rápida por palavras-chave - {total} registros'
+ }
+
+ def _calculate_metrics(
+ self,
+ posts: List[Dict],
+ news: List[Dict]
+ ) -> Dict[str, Any]:
+ """Calcula métricas agregadas."""
+
+ if not posts and not news:
+ return self._empty_metrics()
+
+ # Métricas de posts
+ total_likes = sum(p.get('likesCount', 0) for p in posts)
+ total_comments = sum(p.get('commentsCount', 0) for p in posts)
+ total_engagement = total_likes + total_comments
+
+ # Médias
+ avg_likes = total_likes / len(posts) if posts else 0
+ avg_comments = total_comments / len(posts) if posts else 0
+ avg_engagement = total_engagement / len(posts) if posts else 0
+
+ # Top posts
+ top_by_likes = sorted(posts, key=lambda x: x.get('likesCount', 0), reverse=True)[:5]
+ top_by_engagement = sorted(
+ posts,
+ key=lambda x: x.get('likesCount', 0) + x.get('commentsCount', 0),
+ reverse=True
+ )[:5]
+
+ # Distribuição por perfil
+ profile_dist = {}
+ for post in posts:
+ profile = post.get('profile', 'unknown')
+ if profile not in profile_dist:
+ profile_dist[profile] = {
+ 'count': 0,
+ 'likes': 0,
+ 'comments': 0,
+ 'engagement': 0
+ }
+ profile_dist[profile]['count'] += 1
+ profile_dist[profile]['likes'] += post.get('likesCount', 0)
+ profile_dist[profile]['comments'] += post.get('commentsCount', 0)
+ profile_dist[profile]['engagement'] += (
+ post.get('likesCount', 0) + post.get('commentsCount', 0)
+ )
+
+ # Análise temporal (posts por dia)
+ daily_posts = {}
+ for post in posts:
+ try:
+ post_date = date_parser.parse(post['timestamp'])
+ post_date = self._normalize_datetime(post_date)
+ date_str = post_date.date().isoformat()
+
+ if date_str not in daily_posts:
+ daily_posts[date_str] = {
+ 'count': 0,
+ 'likes': 0,
+ 'comments': 0
+ }
+ daily_posts[date_str]['count'] += 1
+ daily_posts[date_str]['likes'] += post.get('likesCount', 0)
+ daily_posts[date_str]['comments'] += post.get('commentsCount', 0)
+ except Exception as e:
+ print(f"⚠️ Erro ao processar data para análise temporal: {e}")
+
+ # Análise de notícias
+ news_publishers = {}
+ for article in news:
+ pub = article.get('publisher_name', 'Desconhecido')
+ news_publishers[pub] = news_publishers.get(pub, 0) + 1
+
+ return {
+ 'posts': {
+ 'total': len(posts),
+ 'total_likes': total_likes,
+ 'total_comments': total_comments,
+ 'total_engagement': total_engagement,
+ 'avg_likes': round(avg_likes, 2),
+ 'avg_comments': round(avg_comments, 2),
+ 'avg_engagement': round(avg_engagement, 2),
+ 'top_by_likes': [
+ {
+ 'profile': p.get('profile'),
+ 'likes': p.get('likesCount', 0),
+ 'comments': p.get('commentsCount', 0),
+ 'url': p.get('url'),
+ 'caption': p.get('caption', '')[:100] + '...'
+ }
+ for p in top_by_likes
+ ],
+ 'top_by_engagement': [
+ {
+ 'profile': p.get('profile'),
+ 'likes': p.get('likesCount', 0),
+ 'comments': p.get('commentsCount', 0),
+ 'engagement': p.get('likesCount', 0) + p.get('commentsCount', 0),
+ 'url': p.get('url'),
+ 'caption': p.get('caption', '')[:100] + '...'
+ }
+ for p in top_by_engagement
+ ],
+ 'by_profile': profile_dist,
+ 'daily_distribution': daily_posts
+ },
+ 'news': {
+ 'total': len(news),
+ 'by_publisher': news_publishers
+ },
+ 'summary': {
+ 'total_records': len(posts) + len(news),
+ 'posts_count': len(posts),
+ 'news_count': len(news),
+ 'total_engagement': total_engagement,
+ 'avg_engagement_per_post': round(avg_engagement, 2)
+ }
+ }
+
+ def _empty_metrics(self) -> Dict[str, Any]:
+ """Retorna estrutura vazia quando não há dados."""
+ return {
+ 'posts': {
+ 'total': 0,
+ 'total_likes': 0,
+ 'total_comments': 0,
+ 'total_engagement': 0,
+ 'avg_likes': 0,
+ 'avg_comments': 0,
+ 'avg_engagement': 0,
+ 'top_by_likes': [],
+ 'top_by_engagement': [],
+ 'by_profile': {},
+ 'daily_distribution': {}
+ },
+ 'news': {
+ 'total': 0,
+ 'by_publisher': {}
+ },
+ 'summary': {
+ 'total_records': 0,
+ 'posts_count': 0,
+ 'news_count': 0,
+ 'total_engagement': 0,
+ 'avg_engagement_per_post': 0
+ },
+ 'sentiment': { # 🆕
+ 'total_analyzed': 0,
+ 'positive': 0,
+ 'negative': 0,
+ 'neutral': 0,
+ 'positive_pct': 0,
+ 'negative_pct': 0,
+ 'neutral_pct': 0,
+ 'trend': 'neutral',
+ 'profiles': [],
+ 'note': 'Nenhum dado disponível'
+ }
+ }
+
+ def get_date_range_data(
+ self,
+ start_date: Optional[str] = None,
+ end_date: Optional[str] = None,
+ profile_filter: Optional[List[str]] = None,
+ use_llm_sentiment: bool = False,
+ use_cache: bool = True,
+ content_filter: str = "both"
+ ) -> Dict[str, Any]:
+ """
+ Retorna métricas para um intervalo de datas.
+
+ Args:
+ start_date: Data inicial (ISO format)
+ end_date: Data final (ISO format)
+ profile_filter: Lista de perfis para filtrar
+ use_llm_sentiment: Se True, usa LLM para análise de sentimento
+ use_cache: Se True, usa cache de sentimento
+ content_filter: Tipo de conteúdo ("both", "caption", "comments")
+
+ Returns:
+ Dicionário com métricas agregadas
+ """
+ # Busca todos os dados
+ results = self.collection.get(
+ limit=100000,
+ include=['documents', 'metadatas']
+ )
+
+ if not results['ids']:
+ return self._empty_metrics()
+
+ # Filtra por data e perfil
+ filtered_posts = []
+ filtered_news = []
+
+ for i, metadata in enumerate(results['metadatas']):
+ # Filtro de perfil
+ if profile_filter and metadata.get('profile') not in profile_filter:
+ continue
+
+ # Filtro de data
+ if start_date or end_date:
+ try:
+ post_date = date_parser.parse(metadata['timestamp'])
+ post_date = self._normalize_datetime(post_date)
+
+ if start_date:
+ start_dt = date_parser.parse(start_date)
+ start_dt = self._normalize_datetime(start_dt)
+ if post_date < start_dt:
+ continue
+
+ if end_date:
+ end_dt = date_parser.parse(end_date)
+ end_dt = self._normalize_datetime(end_dt)
+ if post_date > end_dt:
+ continue
+ except Exception as e:
+ print(f"⚠️ Erro ao parsear data: {e}")
+ continue
+
+ # Separa posts e notícias
+ content_type = metadata.get('content_type', 'instagram_post')
+ doc_data = {
+ 'text': results['documents'][i],
+ 'metadata': metadata,
+ 'profile': metadata.get('profile', ''),
+ 'url': metadata.get('url', ''),
+ 'timestamp': metadata.get('timestamp', ''),
+ 'likesCount': metadata.get('likesCount', 0),
+ 'commentsCount': metadata.get('commentsCount', 0),
+ 'caption': metadata.get('caption', ''),
+ 'hashtags': metadata.get('hashtags', []),
+ 'mentions': metadata.get('mentions', []),
+ 'type': metadata.get('type', ''),
+ 'content_type': content_type
+ }
+
+ if content_type == 'news':
+ doc_data.update({
+ 'title': metadata.get('title', ''),
+ 'publisher_name': metadata.get('publisher_name', '')
+ })
+ filtered_news.append(doc_data)
+ else:
+ filtered_posts.append(doc_data)
+
+ # Calcula métricas
+ metrics = self._calculate_metrics(filtered_posts, filtered_news)
+
+ # Detecta tópicos emergentes
+ emerging_topics = self._detect_emerging_topics(filtered_posts)
+ metrics['emerging_topics'] = emerging_topics
+
+ # Análise de sentimento (se solicitada)
+ if use_llm_sentiment and filtered_posts:
+ sentiment = self._analyze_sentiment_batch(
+ [{'text': p['text'], 'metadata': p['metadata']} for p in filtered_posts],
+ profiles=profile_filter,
+ use_llm=True
+ )
+ metrics['sentiment'] = sentiment
+ elif filtered_posts:
+ sentiment = self._analyze_sentiment_batch(
+ [{'text': p['text'], 'metadata': p['metadata']} for p in filtered_posts],
+ profiles=profile_filter,
+ use_llm=False
+ )
+ metrics['sentiment'] = sentiment
+
+ return metrics
+
+ def _detect_emerging_topics(self, posts: List[Dict]) -> Dict[str, Any]:
+ """
+ Detecta tópicos emergentes através de análise de temas com LLM.
+
+ Args:
+ posts: Lista de posts com 'caption' e opcionalmente 'comments_text'
+
+ Returns:
+ Dicionário com tópicos emergentes baseados em temas extraídos por LLM
+ """
+ if not posts:
+ return {
+ 'total_topics': 0,
+ 'total_posts_analyzed': 0,
+ 'topics': [],
+ 'top_hashtags': [],
+ 'total_unique_hashtags': 0,
+ 'total_hashtag_occurrences': 0
+ }
+
+ total_posts = len(posts)
+ print(f"🔍 Iniciando análise de temas com LLM para {total_posts} posts...")
+
+ # Contadores
+ theme_counter = {}
+ hashtag_counter = {}
+ total_texts_analyzed = 0
+
+ # Coleta todos os textos individuais
+ all_texts = []
+ batch_size = 20
+
+ for i, post in enumerate(posts):
+ # Legenda
+ caption = post.get('caption', '')
+ if caption and len(caption.strip()) > 10:
+ all_texts.append((caption, 'caption', i))
+
+ # Comentários
+ comments = post.get('comments_text', '')
+ if comments:
+ individual_comments = [c.strip() for c in comments.split('\n\n') if len(c.strip()) > 10]
+ for comment in individual_comments[:5]:
+ all_texts.append((comment, 'comment', i))
+
+ # Processa hashtags
+ hashtags = post.get('hashtags', [])
+ if isinstance(hashtags, list):
+ for tag in hashtags:
+ tag_clean = tag.lower().replace('#', '').strip()
+ tag_valid = ''.join(
+ c for c in tag_clean
+ if c.isalnum() or c in ['á', 'é', 'í', 'ó', 'ú', 'â', 'ê', 'ô', 'ã', 'õ', 'ç', 'ü', 'ñ']
+ )
+ if len(tag_valid) >= 3 and not tag_valid.isdigit():
+ if any(c.isalpha() for c in tag_valid):
+ hashtag_counter[tag_valid] = hashtag_counter.get(tag_valid, 0) + 1
+
+ print(f" 📝 Total de textos coletados: {len(all_texts)}")
+
+ # Processa textos em batches com LLM
+ for i in range(0, len(all_texts), batch_size):
+ batch = all_texts[i:i + batch_size]
+ batch_num = (i // batch_size) + 1
+ total_batches = (len(all_texts) + batch_size - 1) // batch_size
+
+ print(f" 🔮 Processando lote {batch_num}/{total_batches} ({len(batch)} textos)...")
+
+ try:
+ import llm_chat
+ from config import DEFAULT_PROVIDER, DEEPSEEK_MODEL
+
+ texts_numbered = "\n\n".join([
+ f"TEXTO {j+1}:\n{text[:400]}"
+ for j, (text, _, _) in enumerate(batch)
+ ])
+
+ prompt = f"""Você é um especialista em análise de comunicação universitária.
+
+Analise cada um dos {len(batch)} textos abaixo e extraia o TEMA CENTRAL de cada um.
+
+INSTRUÇÕES:
+- Retorne um rótulo de tema CONCISO (2-5 palavras) que capture a essência do texto
+- Normalize temas similares para o mesmo rótulo
+- Se o texto for muito genérico, use "Outros"
+- Seja consistente nos rótulos
+
+TEXTOS:
+{texts_numbered}
+
+Retorne APENAS um JSON com o formato:
+{{
+ "themes": ["Tema 1", "Tema 2", ...]
+}}
+
+A lista deve ter EXATAMENTE {len(batch)} elementos."""
+
+ model = DEEPSEEK_MODEL if DEFAULT_PROVIDER == 'deepseek' else "qwen3:30b"
+
+ response = llm_chat.chat(
+ model=model,
+ messages=[{'role': 'user', 'content': prompt}]
+ )
+
+ response_text = response['message']['content']
+
+ if '```json' in response_text:
+ response_text = response_text.split('```json')[1].split('```')[0]
+ elif '```' in response_text:
+ response_text = response_text.split('```')[1].split('```')[0]
+
+ import json
+ result = json.loads(response_text.strip())
+ themes = result.get('themes', [])
+
+ if len(themes) != len(batch):
+ print(f" ⚠️ LLM retornou {len(themes)} temas, esperado {len(batch)}. Usando fallback.")
+ themes = ["Outros"] * len(batch)
+
+ for theme in themes:
+ theme_normalized = ' '.join(word.capitalize() for word in theme.strip().split())
+ theme_counter[theme_normalized] = theme_counter.get(theme_normalized, 0) + 1
+ total_texts_analyzed += 1
+
+ print(f" ✓ Lote processado: {len(themes)} temas extraídos")
+
+ except Exception as e:
+ print(f" ❌ Erro ao processar lote {batch_num}: {e}")
+ theme_counter["Outros"] = theme_counter.get("Outros", 0) + len(batch)
+ total_texts_analyzed += len(batch)
+
+ print(f" ✅ Análise concluída: {len(theme_counter)} temas únicos identificados")
+
+ # Remove tema genérico se houver temas específicos
+ if len(theme_counter) > 1 and "Outros" in theme_counter:
+ if theme_counter["Outros"] < total_texts_analyzed * 0.3:
+ del theme_counter["Outros"]
+
+ # Top temas
+ top_themes = sorted(theme_counter.items(), key=lambda x: x[1], reverse=True)[:10]
+
+ # Top hashtags
+ top_hashtags = sorted(hashtag_counter.items(), key=lambda x: x[1], reverse=True)[:5]
+
+ # Monta resposta
+ topics = []
+
+ for theme, count in top_themes:
+ percentage = (count / total_texts_analyzed * 100) if total_texts_analyzed > 0 else 0
+
+ if percentage >= 15.0:
+ growth = 75
+ elif percentage >= 10.0:
+ growth = 60
+ elif percentage >= 5.0:
+ growth = 45
+ elif percentage >= 3.0:
+ growth = 30
+ else:
+ growth = 10
+
+ topics.append({
+ 'term': theme,
+ 'count': count,
+ 'percentage': round(percentage, 1),
+ 'growth_indicator': growth
+ })
+
+ hashtags_list = [
+ {
+ 'tag': tag,
+ 'count': count,
+ 'percentage': round((count / total_posts) * 100, 1),
+ 'posts_with_tag': count
+ }
+ for tag, count in top_hashtags
+ ]
+
+ print(f"🎯 Resultado final:")
+ print(f" - {len(topics)} temas principais identificados")
+ print(f" - {total_texts_analyzed} textos analisados")
+ if topics:
+ print(f" - Top 3 temas: {[t['term'] for t in topics[:3]]}")
+
+ return {
+ 'total_topics': len(topics),
+ 'total_posts_analyzed': total_posts,
+ 'topics': topics,
+ 'top_hashtags': hashtags_list,
+ 'total_unique_hashtags': len(hashtag_counter),
+ 'total_hashtag_occurrences': sum(hashtag_counter.values()),
+ 'analysis_method': 'llm_theme_extraction'
+ }
\ No newline at end of file
diff --git a/app.py b/app.py
index 6ee71da..7c14bb1 100644
--- a/app.py
+++ b/app.py
@@ -4,14 +4,27 @@
"""
import gradio as gr
-from agent_system import RAGAgent
-from rag_system import RAGSystem
-from ping_theme import ping_theme
-from datetime import datetime
-from typing import List, Tuple, Dict
+from datetime import datetime, timedelta
+from typing import List, Tuple, Dict, Optional, Any
import json
import os
from pathlib import Path
+import tempfile
+from data_ingestion import DataIngestion
+
+# 🔧 Configurar diretório temporário do Gradio para evitar problemas de permissão
+custom_temp_dir = Path.home() / ".cache" / "gradio"
+custom_temp_dir.mkdir(parents=True, exist_ok=True)
+os.environ["GRADIO_TEMP_DIR"] = str(custom_temp_dir)
+
+# 🔧 IMPORTS CORRIGIDOS - usar agent_system e rag_system
+from agent_system import RAGAgent
+from rag_system import RAGSystem
+from embedding_manager import EmbeddingManager
+from analytics_dashboard import DashboardAnalytics
+from dashboard_visualizer import DashboardVisualizer
+from report_exporter import ReportExporter
+from ping_theme import ping_theme
class HistoryManager:
@@ -112,57 +125,118 @@ def __init__(
use_agent: bool = True
):
"""
- Inicializa a aplicação.
+ Inicializa o sistema RAG.
Args:
- embedding_model: Modelo para embeddings
- generation_model: Modelo para geração
- use_agent: Se True, usa sistema de agente (recomendado)
+ embedding_model: Modelo de embeddings
+ generation_model: Modelo de geração
+ use_agent: Se True, usa sistema de agentes
"""
- print("🚀 Iniciando aplicação RAG...")
-
+ # 🔧 Armazena modelos
+ self.embedding_model = embedding_model
+ self.generation_model = generation_model
self.use_agent = use_agent
- self.history_manager = HistoryManager()
+ # 🔧 Inicializa sistema apropriado (Agente ou RAG Clássico)
if use_agent:
- # Inicializa sistema de agente inteligente
- print("🤖 Modo: Agente Inteligente (LLM decide quais ferramentas usar)")
+ # Modo Agente - passa os nomes dos modelos (não o EmbeddingManager)
+ from agent_system import RAGAgent
+
self.agent = RAGAgent(
embedding_model=embedding_model,
generation_model=generation_model,
- planning_model=generation_model # Pode usar modelo mais leve aqui
+ planning_model=generation_model # Usa mesmo modelo para planejamento
)
- # Mantém referência ao embedding_manager para stats
+
+ # Pega referência ao embedding_manager do agente
self.embedding_manager = self.agent.embedding_manager
+
+ self.query_engine = self.agent # Compatibilidade
+ print(" ✅ RAGAgent inicializado")
else:
- # Sistema antigo com detecção de keywords
- print("🔧 Modo: Sistema Clássico (detecção por palavras-chave)")
- self.rag = RAGSystem(
- embedding_model=embedding_model,
- generation_model=generation_model
- )
- self.embedding_manager = self.rag.embedding_manager
-
- # Indexa posts na inicialização (se não usar agente)
- if not use_agent:
- print("\n📊 Verificando índice de posts...")
- self.rag.index_all_posts()
- self.stats = self.rag.get_system_stats()
- posts_count = self.stats.get('indexed_posts', 0)
- else:
- # Para o agente, verifica stats do embedding manager
- em_stats = self.embedding_manager.get_stats()
- # Adapta estrutura para compatibilidade
- self.stats = {
- 'indexed_posts': em_stats.get('total_documents', 0),
- 'profiles': em_stats.get('profiles', []),
- 'embedding_model': em_stats.get('embedding_model', 'unknown'),
- 'collection_name': em_stats.get('collection_name', 'unknown')
- }
- posts_count = self.stats['indexed_posts']
- print(f"📊 Perfis detectados: {self.stats['profiles']}")
+ # Modo RAG Clássico
+ from rag_system import RAGSystem
+ from embedding_manager import EmbeddingManager
+
+ # Cria embedding_manager primeiro
+ self.embedding_manager = EmbeddingManager(embedding_model)
+
+ try:
+ self.rag = RAGSystem(
+ embedding_manager=self.embedding_manager,
+ generation_model=generation_model
+ )
+ except TypeError:
+ # Fallback: cria stub simples
+ class SimpleRAGSystem:
+ def __init__(self, embedding_manager, generation_model):
+ self.embedding_manager = embedding_manager
+ self.generation_model = generation_model
+ self.collection = embedding_manager.collection
+
+ def query(self, question, n_results=5, profile_filter=None):
+ import llm_chat
+ results = self.embedding_manager.search(
+ query=question,
+ n_results=n_results,
+ profile_filter=profile_filter
+ )
+ context = "\n\n".join([
+ f"@{d['metadata']['profile']}: {d['document'][:300]}"
+ for d in results['documents']
+ ])
+ prompt = f"Pergunta: {question}\n\nContexto:\n{context}\n\nResposta:"
+ response = llm_chat.chat(
+ model=self.generation_model,
+ messages=[{'role': 'user', 'content': prompt}]
+ )
+ return response['message']['content'], results['documents']
+
+ self.rag = SimpleRAGSystem(
+ self.embedding_manager,
+ generation_model
+ )
+
+ self.query_engine = self.rag # Compatibilidade
+ print(" ✅ RAGSystem inicializado")
- print(f"\n✓ Sistema pronto com {posts_count} posts indexados")
+ # Histórico
+ self.history_manager = HistoryManager()
+
+ # 🆕 Analytics (usa o embedding_manager já criado)
+ from analytics_dashboard import DashboardAnalytics
+ from dashboard_visualizer import DashboardVisualizer
+
+ self.analytics = DashboardAnalytics(self.embedding_manager)
+ self.dashboard_visualizer = DashboardVisualizer()
+
+ # Adiciona referência ao analytics no app para dashboard
+ self.dashboard_analytics = self.analytics
+
+ # 🔧 Stats - agora com fallback para estrutura correta
+ raw_stats = self.embedding_manager.get_stats()
+
+ # Normaliza estrutura de stats (compatibilidade)
+ self.stats = {
+ 'total': raw_stats.get('total', raw_stats.get('indexed_posts', 0)),
+ 'indexed_posts': raw_stats.get('indexed_posts', raw_stats.get('total', 0)),
+ 'profiles': raw_stats.get('profiles', []),
+ 'embedding_model': raw_stats.get('embedding_model', embedding_model)
+ }
+
+ print(f"✅ Sistema inicializado")
+ print(f" 📊 Registros indexados: {self.stats['total']}")
+ print(f" 🤖 Modelo: {generation_model}")
+ print(f" 🎯 Modo: {'Agente' if use_agent else 'RAG Simples'}")
+
+ # Inicializa gerenciador de ingestão
+ self.data_ingestion = DataIngestion()
+
+ # Inicializar cache
+ self.dashboard_cache = DashboardCache(
+ cache_file="dashboard_cache.json",
+ ttl_minutes=30 # Cache válido por 30 minutos
+ )
def format_sources(self, posts: List[dict]) -> str:
"""
@@ -341,6 +415,74 @@ def format_sources(self, posts: List[dict]) -> str:
"""
+ # ⭐ NOVA SEÇÃO: Análise de Hashtags
+ if data.get('hashtag_analysis') and data['hashtag_analysis'].get('total_unique', 0) > 0:
+ hashtag_data = data['hashtag_analysis']
+ html += f"""
+
+
🏷️ Análise de Hashtags
+
+ - Total de hashtags únicas: {hashtag_data['total_unique']}
+ - Total de ocorrências: {hashtag_data['total_occurrences']}
+ - Média por post: {hashtag_data['avg_per_post']}
+
+
Top Hashtags:
+
+ """
+
+ for tag_data in hashtag_data['top_hashtags'][:5]:
+ html += f"""
+
+ #{tag_data['tag']} ({tag_data['count']} • {tag_data['percentage']}%)
+
+ """
+
+ html += """
+
+
+ """
+
+ # ⭐ NOVA SEÇÃO: Análise de Menções
+ if data.get('mention_analysis') and data['mention_analysis'].get('total_unique', 0) > 0:
+ mention_data = data['mention_analysis']
+ html += f"""
+
+
👥 Análise de Menções
+
+ - Total de menções únicas: {mention_data['total_unique']}
+ - Total de ocorrências: {mention_data['total_occurrences']}
+ - Média por post: {mention_data['avg_per_post']}
+
+
Top Menções:
+
+ """
+
+ for mention_data_item in mention_data['top_mentions'][:5]:
+ html += f"""
+
+ {mention_data_item['username']} ({mention_data_item['count']} • {mention_data_item['percentage']}%)
+
+ """
+
+ html += """
+
+
+ """
+
# Distribuição de sentimentos (gráfico visual)
total = data['positive_count'] + data['negative_count'] + data['neutral_count']
pos_pct = (data['positive_count'] / total * 100) if total > 0 else 0
@@ -353,24 +495,27 @@ def format_sources(self, posts: List[dict]) -> str:
✅ Positivo:
-
-
+
+
+ {data['positive_count']} ({pos_pct:.1f}%)
+
-
{data['positive_count']} ({pos_pct:.1f}%)
❌ Negativo:
-
-
+
+
+ {data['negative_count']} ({neg_pct:.1f}%)
+
-
{data['negative_count']} ({neg_pct:.1f}%)
⚪ Neutro:
-
-
+
+
+ {data['neutral_count']} ({neu_pct:.1f}%)
+
-
{data['neutral_count']} ({neu_pct:.1f}%)
@@ -666,14 +811,62 @@ def chat_response(
return response, sources_html
- def get_dashboard_html(self) -> str:
+ def get_analytics_dashboard_html(
+ self,
+ start_date: str = None,
+ end_date: str = None,
+ profile_filter: list = None,
+ content_filter: str = "both" # 🆕 Parâmetro de filtro de conteúdo
+ ) -> str:
"""
- Retorna HTML com dashboard de estatísticas profissional.
- Usa variáveis CSS para compatibilidade com light/dark mode.
+ Retorna HTML do dashboard de análise com filtros aplicados.
+
+ Args:
+ start_date: Data inicial (YYYY-MM-DD)
+ end_date: Data final (YYYY-MM-DD)
+ profile_filter: Lista de perfis selecionados
+ content_filter: Tipo de conteúdo ("both", "caption", "comments")
Returns:
- HTML formatado com dashboard
+ HTML formatado
+ """
+ try:
+ # Converte perfis (remove @ se necessário)
+ if profile_filter:
+ profile_filter = [p.replace('@', '') for p in profile_filter]
+
+ # Busca métricas (🆕 passa content_filter)
+ metrics = self.dashboard_analytics.get_date_range_data(
+ start_date=start_date,
+ end_date=end_date,
+ profile_filter=profile_filter,
+ content_filter=content_filter # 🆕
+ )
+
+ # Gera HTML
+ return self.dashboard_visualizer.generate_dashboard_html(metrics)
+
+ except Exception as e:
+ return f"""
+
+
❌ Erro ao carregar dashboard
+
{str(e)}
+
+ """
+
+ def get_dashboard_html(self) -> str:
"""
+ Retorna HTML com dashboard (usa cache se disponível).
+ """
+ # Tenta usar cache primeiro
+ cached_html = self.dashboard_cache.get('dashboard_html')
+ if cached_html:
+ print("✅ Dashboard: usando cache")
+ return cached_html
+
+ print("🔄 Dashboard: gerando nova estatística...")
+
+ # Gera estatísticas (código atual)
history_stats = self.history_manager.get_stats()
generation_model = self.agent.generation_model if self.use_agent else self.rag.generation_model
@@ -890,6 +1083,388 @@ def get_stats_html(self) -> str:
"""
return html
+ def get_sentiment_card_html(
+ self,
+ profile_filter: Optional[str] = None,
+ start_date: Optional[str] = None,
+ end_date: Optional[str] = None,
+ use_cache: bool = True,
+ content_filter: str = "both" # 🆕 Filtro de conteúdo
+ ) -> str:
+ """
+ Retorna HTML do card de análise de sentimento.
+
+ Args:
+ profile_filter: Perfil específico para analisar (ex: "dceuff")
+ start_date: Data inicial
+ end_date: Data final
+ use_cache: Se True, usa cache (padrão: True)
+ content_filter: Tipo de conteúdo ("both", "caption", "comments")
+
+ Returns:
+ HTML formatado com análise de sentimento
+ """
+ from analytics_dashboard import DashboardAnalytics
+
+ analytics = DashboardAnalytics(
+ self.agent.embedding_manager if self.use_agent else self.rag.embedding_manager
+ )
+
+ # Se tem filtro de perfil, usa método específico
+ if profile_filter and profile_filter != "Todos":
+ sentiment = analytics.get_sentiment_by_profile(
+ profile=profile_filter,
+ start_date=start_date,
+ end_date=end_date,
+ use_cache=use_cache,
+ content_filter=content_filter # 🆕 Passa filtro
+ )
+ else:
+ # Análise geral
+ metrics = analytics.get_date_range_data(
+ start_date=start_date,
+ end_date=end_date,
+ use_cache=use_cache,
+ content_filter=content_filter # 🆕 Passa filtro
+ )
+ sentiment = metrics.get('sentiment', {})
+
+ # Dados do sentimento
+ total = sentiment.get('total_analyzed', 0)
+ positive = sentiment.get('positive', 0)
+ negative = sentiment.get('negative', 0)
+ neutral = sentiment.get('neutral', 0)
+
+ pos_pct = sentiment.get('positive_pct', 0)
+ neg_pct = sentiment.get('negative_pct', 0)
+ neu_pct = sentiment.get('neutral_pct', 0)
+
+ trend = sentiment.get('trend', 'neutral')
+ profile_name = sentiment.get('display_name', 'Todos os perfis')
+
+ # 🆕 Status do cache
+ cached = sentiment.get('cached', False)
+ cache_icon = "💾" if cached else "🆕"
+ cache_text = "Dados do cache" if cached else "Análise nova"
+
+ # 🆕 Tipo de conteúdo analisado
+ content_type_label = {
+ "both": "Legendas + Comentários",
+ "caption": "Apenas Legendas",
+ "comments": "Apenas Comentários"
+ }.get(content_filter, "Legendas + Comentários")
+
+ # Emoji da tendência
+ trend_emoji = {
+ 'positive': '😊',
+ 'negative': '😟',
+ 'neutral': '😐'
+ }.get(trend, '😐')
+
+ # Cor da tendência
+ trend_color = {
+ 'positive': '#4caf50',
+ 'negative': '#f44336',
+ 'neutral': '#9e9e9e'
+ }.get(trend, '#9e9e9e')
+
+ html = f"""
+
+
+
🎭 Análise de Sentimento
+ {trend_emoji}
+
+
+
+ {profile_name} • {total} registros analisados
+
+
+
+
+ 📝 Analisando: {content_type_label}
+
+
+
+
+
+ {cache_icon} {cache_text}
+
+
+
+
+
+
+
✅ Positivo:
+
+
{positive} ({pos_pct}%)
+
+
+
+
❌ Negativo:
+
+
{negative} ({neg_pct}%)
+
+
+
+
⚪ Neutro:
+
+
{neutral} ({neu_pct}%)
+
+
+
+
+ 💡 {sentiment.get('note', 'Análise baseada em palavras-chave')}
+
+
+ """
+
+ return html
+
+ def export_dashboard_report(
+ self,
+ format: str,
+ start_date: str = None,
+ end_date: str = None,
+ profile_filter: list = None,
+ content_filter: str = "both"
+ ) -> Tuple[str, Any]:
+ """
+ 🆕 Exporta relatório do dashboard.
+
+ Args:
+ format: Formato ('csv' ou 'pdf')
+ start_date: Data inicial
+ end_date: Data final
+ profile_filter: Lista de perfis
+ content_filter: Tipo de conteúdo
+
+ Returns:
+ Tuple (filepath, content)
+ """
+ try:
+ # Limpa perfis
+ if profile_filter:
+ profile_filter = [p.replace('@', '') for p in profile_filter]
+
+ # Busca métricas
+ metrics = self.dashboard_analytics.get_date_range_data(
+ start_date=start_date,
+ end_date=end_date,
+ profile_filter=profile_filter,
+ use_llm_sentiment=False, # Usa cache
+ use_cache=True,
+ content_filter=content_filter
+ )
+
+ # 🆕 ADICIONA RECOMENDAÇÕES DE POLÍTICA ao relatório
+ try:
+ print("\n🔮 Gerando recomendações de políticas para o relatório...")
+ profile = profile_filter[0] if profile_filter and len(profile_filter) == 1 else None
+
+ recommendations = self.dashboard_analytics.generate_policy_recommendations(
+ profile_filter=profile,
+ min_engagement=100,
+ top_n=5
+ )
+
+ # 🔧 TRANSFORMA formato LLM para formato do exportador
+ if recommendations and recommendations.get('recommendations'):
+ from datetime import datetime
+
+ # Extrai dados de sentimento
+ sentiment_data = recommendations.get('sentiment_analysis', {})
+
+ # Monta formato esperado pelo exportador
+ export_format = {
+ 'has_recommendations': True,
+ 'generated_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
+ 'profile': f"@{profile}" if profile else "Todos os perfis",
+ 'content_filter': content_filter,
+ 'sentiment_data': sentiment_data,
+ 'summary': f"Análise baseada em {len(recommendations.get('recommendations', []))} recomendações geradas automaticamente.",
+ 'critical_areas': recommendations.get('critical_areas', []),
+ 'recommendations': recommendations.get('recommendations', []),
+ 'positive_aspects': recommendations.get('positive_aspects', []),
+ 'general_observations': f"Sentimento: {sentiment_data.get('positive_pct', 0):.1f}% positivo, {sentiment_data.get('negative_pct', 0):.1f}% negativo"
+ }
+
+ metrics['policy_recommendations'] = export_format
+ print(f"✅ {len(recommendations['recommendations'])} recomendações incluídas no relatório")
+ else:
+ print("⚠️ Nenhuma recomendação gerada (dados insuficientes)")
+ except Exception as e:
+ print(f"⚠️ Erro ao gerar recomendações: {e}")
+ import traceback
+ traceback.print_exc()
+
+ # 🔧 CORRIGIDO: Usa diretório local em vez de /tmp
+ timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
+ filename = f"relatorio_uff_{timestamp}.{format}"
+
+ content = self.dashboard_analytics.export_report(metrics, format, filename)
+
+ # Cria diretório de exports se não existir
+ exports_dir = Path('./exports')
+ exports_dir.mkdir(exist_ok=True)
+
+ # Salva arquivo local
+ filepath = exports_dir / filename
+ if format == 'csv':
+ with open(filepath, 'w', encoding='utf-8') as f:
+ f.write(content)
+ else: # PDF
+ with open(filepath, 'wb') as f:
+ f.write(content)
+
+ print(f"✅ Relatório salvo: {filepath}")
+ return str(filepath), content
+
+ except Exception as e:
+ print(f"❌ Erro ao exportar relatório: {e}")
+ import traceback
+ traceback.print_exc()
+ return None, None
+
+ def process_upload(
+ self,
+ file,
+ profile_name: str,
+ content_type: str = "custom_ingestion", # 🆕 NOVO PARÂMETRO
+ text_column: str = "text",
+ auto_index: bool = True
+ ) -> tuple[str, str]:
+ """
+ Processa arquivo enviado pelo usuário.
+
+ Args:
+ file: Arquivo enviado
+ profile_name: Nome do perfil/fonte
+ content_type: Tipo de conteúdo (aparece na interface)
+ text_column: Nome da coluna com texto (CSV)
+ auto_index: Se True, indexa automaticamente
+
+ Returns:
+ (status_html, preview_html)
+ """
+ if file is None:
+ return "⚠️ Nenhum arquivo selecionado", ""
+
+ import shutil
+ from pathlib import Path
+
+ # Salva arquivo temporário
+ temp_path = Path(self.data_ingestion.temp_dir) / Path(file.name).name
+ shutil.copy(file.name, temp_path)
+
+ # Processa arquivo (🆕 passa content_type)
+ documents, status = self.data_ingestion.process_file(
+ temp_path,
+ profile_name=profile_name,
+ content_type=content_type, # 🆕 NOVO PARÂMETRO
+ text_column=text_column
+ )
+
+ if not documents:
+ return f"
{status}
", ""
+
+ # Preview dos primeiros documentos
+ preview_html = self._generate_preview_html(documents[:5])
+
+ # Se auto-index ativado, indexa no ChromaDB
+ if auto_index and documents:
+ try:
+ if self.use_agent:
+ self.agent.embedding_manager.add_posts(documents)
+ else:
+ self.embedding_manager.add_posts(documents)
+
+ status += f"
✅ {len(documents)} documentos indexados no ChromaDB"
+
+ # Atualiza stats
+ self._refresh_stats()
+ except Exception as e:
+ status += f"
⚠️ Erro ao indexar: {e}"
+
+ status_html = f"
{status}
"
+
+ # DEPOIS (preserva o arquivo)
+ final_path = self.data_ingestion.data_dir / f"{profile_name}_{datetime.now().strftime('%Y%m%d_%H%M%S')}_{temp_path.name}"
+ shutil.move(temp_path, final_path)
+ status += f"
💾 Arquivo salvo em: {final_path}"
+
+ return status_html, preview_html
+
+ def _generate_preview_html(self, documents: List[Dict]) -> str:
+ """Gera HTML de preview dos documentos."""
+ html = "
"
+ html += "
📄 Preview dos Documentos
"
+
+ for i, doc in enumerate(documents, 1):
+ html += f"""
+
+
Documento {i}
+
+ ID: {doc['id']}
+ Perfil: {doc['profile']}
+ Tipo: {doc['content_type']}
+
+
+ Texto:
+ {doc['text'][:300]}{'...' if len(doc['text']) > 300 else ''}
+
+
+ """
+
+ if len(documents) > 5:
+ html += f"
... e mais {len(documents) - 5} documentos
"
+
+ html += "
"
+ return html
+
+ def _refresh_stats(self):
+ """Atualiza estatísticas após ingestão."""
+ if self.use_agent:
+ em_stats = self.agent.embedding_manager.get_stats()
+ else:
+ em_stats = self.embedding_manager.get_stats()
+
+ self.stats['indexed_posts'] = em_stats.get('total_documents', 0)
+ self.stats['profiles'] = em_stats.get('profiles', [])
+
def create_interface(self) -> gr.Blocks:
"""
Cria interface Gradio profissional com abas navegáveis.
@@ -1003,9 +1578,287 @@ def create_interface(self) -> gr.Blocks:
gr.Markdown(f"__{mode_text}__")
# ===== ABA 2: ESTATÍSTICAS =====
- with gr.TabItem("📊 Estatísticas"):
- dashboard_html = gr.HTML(value=self.get_dashboard_html())
-
+ with gr.TabItem("📊 Dashboard"):
+ with gr.Row():
+ with gr.Column(scale=9):
+ dashboard_display = gr.HTML(value=self.get_analytics_dashboard_html())
+
+ with gr.Column(scale=3, elem_classes="sidebar-config"):
+ gr.Markdown("### 🎯 Filtros de Análise")
+
+ # Filtro de período
+ gr.Markdown("**📅 Período**")
+
+ from datetime import datetime, timedelta
+ today = datetime.now()
+ default_start = (today - timedelta(days=30)).strftime('%Y-%m-%d')
+ default_end = today.strftime('%Y-%m-%d')
+
+ date_start = gr.Textbox(
+ label="Data Inicial (YYYY-MM-DD)",
+ value=default_start,
+ placeholder="2024-01-01"
+ )
+
+ date_end = gr.Textbox(
+ label="Data Final (YYYY-MM-DD)",
+ value=default_end,
+ placeholder="2024-12-31"
+ )
+
+ # Botões de período rápido
+ gr.Markdown("**⚡ Períodos Rápidos**")
+
+ with gr.Row():
+ btn_7days = gr.Button("Últimos 7 dias", size="sm")
+ btn_30days = gr.Button("Últimos 30 dias", size="sm")
+
+ with gr.Row():
+ btn_90days = gr.Button("Últimos 90 dias", size="sm")
+ btn_all = gr.Button("Tudo", size="sm")
+
+ gr.Markdown("---")
+
+ # Filtro de perfis
+ dashboard_profile_filter = gr.CheckboxGroup(
+ choices=["@" + p for p in self.stats['profiles']],
+ value=["@" + p for p in self.stats['profiles']],
+ label="📊 Fontes",
+ interactive=True
+ )
+
+ gr.Markdown("---")
+
+ # 🆕 FILTRO DE CONTEÚDO PARA SENTIMENTO
+ gr.Markdown("**🎭 Análise de Sentimento**")
+
+ sentiment_content_filter = gr.Radio(
+ choices=[
+ ("📝 Legendas + Comentários", "both"),
+ ("🏷️ Apenas Legendas", "caption"),
+ ("💬 Apenas Comentários", "comments")
+ ],
+ value="both",
+ label="Tipo de Conteúdo",
+ interactive=True,
+ info="Escolha qual conteúdo analisar"
+ )
+
+ gr.Markdown("---")
+
+ # Botão de atualizar
+ update_dashboard_btn = gr.Button(
+ "🔄 Atualizar Dashboard",
+ variant="primary",
+ size="lg"
+ )
+
+ gr.Markdown("---")
+
+ # 🆕 SEÇÃO DE EXPORTAÇÃO
+ gr.Markdown("### 📥 Exportar Relatório")
+
+ export_format = gr.Radio(
+ choices=[
+ ("📄 CSV (Excel)", "csv"),
+ ("📕 PDF (Documento)", "pdf")
+ ],
+ value="csv",
+ label="Formato",
+ interactive=True
+ )
+
+ export_btn = gr.Button(
+ "📥 Baixar Relatório",
+ variant="secondary",
+ size="lg"
+ )
+
+ export_status = gr.Textbox(
+ label="Status",
+ interactive=False,
+ visible=False
+ )
+
+ export_file = gr.File(
+ label="Arquivo Gerado",
+ visible=False
+ )
+
+ gr.Markdown("---")
+
+ gr.Markdown("""
+ ### 💡 Dica
+
+ Selecione o período, fontes e tipo de conteúdo,
+ depois clique em **Atualizar Dashboard**
+ para visualizar as métricas.
+
+ **Tipos de Conteúdo:**
+ - **Legendas + Comentários**: Análise completa
+ - **Apenas Legendas**: Sentimento do autor
+ - **Apenas Comentários**: Sentimento da comunidade
+
+ **Exportação:**
+ Escolha CSV ou PDF e clique em **Baixar Relatório**
+ para gerar um arquivo com todas as métricas.
+ """)
+
+ # Funções de atualização do dashboard
+ def set_period(days: int):
+ """Define período rápido."""
+ end = datetime.now()
+ start = end - timedelta(days=days)
+ return start.strftime('%Y-%m-%d'), end.strftime('%Y-%m-%d')
+
+ def set_all_time():
+ """Define período total."""
+ return "2000-01-01", datetime.now().strftime('%Y-%m-%d')
+
+ def update_dashboard(start: str, end: str, profiles: list, content_filter: str):
+ """Atualiza dashboard com filtros."""
+ return self.get_analytics_dashboard_html(
+ start_date=start if start else None,
+ end_date=end if end else None,
+ profile_filter=profiles if profiles else None,
+ content_filter=content_filter
+ )
+
+ # 🆕 Função de exportação
+ def handle_export(fmt, start, end, profiles, content_filter):
+ """Processa exportação de relatório."""
+ filepath, content = self.export_dashboard_report(
+ format=fmt,
+ start_date=start,
+ end_date=end,
+ profile_filter=profiles,
+ content_filter=content_filter
+ )
+
+ if filepath:
+ filename = filepath.split('/')[-1]
+ return (
+ gr.update(value=f"✅ Relatório gerado: {filename}", visible=True),
+ gr.update(value=filepath, visible=True)
+ )
+ else:
+ return (
+ gr.update(value="❌ Erro ao gerar relatório", visible=True),
+ gr.update(visible=False)
+ )
+
+ # Conecta botões de período rápido
+ btn_7days.click(
+ lambda: set_period(7),
+ outputs=[date_start, date_end]
+ )
+
+ btn_30days.click(
+ lambda: set_period(30),
+ outputs=[date_start, date_end]
+ )
+
+ btn_90days.click(
+ lambda: set_period(90),
+ outputs=[date_start, date_end]
+ )
+
+ btn_all.click(
+ set_all_time,
+ outputs=[date_start, date_end]
+ )
+
+ # Conecta botão de atualizar
+ update_dashboard_btn.click(
+ update_dashboard,
+ inputs=[date_start, date_end, dashboard_profile_filter, sentiment_content_filter],
+ outputs=dashboard_display
+ )
+
+ # 🆕 Conecta botão de exportação
+ export_btn.click(
+ fn=handle_export,
+ inputs=[
+ export_format,
+ date_start,
+ date_end,
+ dashboard_profile_filter,
+ sentiment_content_filter
+ ],
+ outputs=[export_status, export_file]
+ )
+
+ # 🆕 Botão de recomendações
+ gr.Markdown("---")
+
+ generate_recommendations_btn = gr.Button(
+ "🔮 Gerar Recomendações de Políticas",
+ variant="secondary",
+ size="lg"
+ )
+
+ gr.Markdown("""
+ **ℹ️ Sobre as recomendações:**
+
+ A IA analisa críticas e comentários negativos para sugerir
+ ações concretas de melhoria. Usa a mesma análise de sentimento
+ já realizada.
+ """)
+
+ # Adicionar callback do botão:
+
+ def generate_recommendations(
+ start, end, profiles, sent_filter
+ ):
+ """Gera recomendações baseadas em análise de sentimento."""
+ try:
+ print("\n🔮 Gerando recomendações de políticas...")
+ profile = profiles[0] if profiles and len(profiles) == 1 else None
+
+ recommendations = self.analytics.generate_policy_recommendations(
+ profile_filter=profile,
+ min_engagement=100,
+ top_n=5
+ )
+
+ # 🔍 DEBUG
+ print(f"🔍 DEBUG recommendations: {recommendations}")
+ print(f" Tem 'recommendations' key? {('recommendations' in recommendations)}")
+ if 'recommendations' in recommendations:
+ print(f" Quantidade: {len(recommendations['recommendations'])}")
+
+ if not recommendations or not recommendations.get('recommendations') or len(recommendations.get('recommendations', [])) == 0:
+ return f"""
+
+
⚠️ Sem Recomendações
+
Dados insuficientes para gerar recomendações.
+
+ """
+
+ # Gera HTML das recomendações
+ from dashboard_visualizer import DashboardVisualizer
+ html = DashboardVisualizer._generate_policy_recommendations_card(recommendations)
+
+ return html
+
+ except Exception as e:
+ print(f"Erro ao gerar recomendações: {e}")
+ import traceback
+ traceback.print_exc()
+ return f"
❌ Erro: {str(e)}
"
+
+ # Conecta botão
+ generate_recommendations_btn.click(
+ fn=generate_recommendations,
+ inputs=[
+ date_start,
+ date_end,
+ dashboard_profile_filter,
+ sentiment_content_filter
+ ],
+ outputs=dashboard_display
+ )
+
# ===== ABA 3: HISTÓRICO =====
with gr.TabItem("📚 Histórico"):
with gr.Row():
@@ -1041,7 +1894,190 @@ def search_history(query):
outputs=history_html
)
- # ===== ABA 4: DOCUMENTAÇÃO =====
+ # ===== ABA 4: INGESTÃO DE DADOS (ATUALIZADA) =====
+ with gr.TabItem("📥 Ingestão de Dados"):
+ gr.HTML("""
+
+
📥 Gerenciar Dados
+
+ Adicione novos dados ou gerencie fontes existentes no banco vetorial.
+
+
+ """)
+
+ with gr.Tabs():
+ # Sub-aba: Upload
+ with gr.TabItem("📤 Upload de Novos Dados"):
+ with gr.Row():
+ with gr.Column(scale=7):
+ # Upload de arquivo
+ file_upload = gr.File(
+ label="📁 Selecione o Arquivo",
+ file_types=['.json', '.csv', '.txt', '.pdf'],
+ type="filepath"
+ )
+
+ # Configurações
+ with gr.Row():
+ profile_name_input = gr.Textbox(
+ label="Nome da Fonte/Perfil",
+ placeholder="Ex: pesquisa_alunos, relatorio_2024",
+ value="custom_data"
+ )
+ # 🆕 NOVO CAMPO: Tipo de Conteúdo
+ content_type_input = gr.Textbox(
+ label="Tipo de Conteúdo",
+ placeholder="Ex: pesquisa, debate, relatorio",
+ value="custom_ingestion",
+ info="Aparecerá como: 📄 [seu_tipo]: X documentos"
+ )
+
+ text_column_input = gr.Textbox(
+ label="Coluna de Texto (CSV)",
+ placeholder="Nome da coluna com texto principal",
+ value="text"
+ )
+
+ auto_index_checkbox = gr.Checkbox(
+ label="✅ Indexar automaticamente no ChromaDB",
+ value=True
+ )
+
+ process_btn = gr.Button(
+ "🚀 Processar e Indexar",
+ variant="primary",
+ size="lg"
+ )
+
+ # Status
+ status_output = gr.HTML()
+
+ # Preview
+ preview_output = gr.HTML()
+
+ # Painel lateral com informações
+ with gr.Column(scale=3):
+ gr.Markdown("### 📋 Formatos Suportados")
+ gr.Markdown("""
+ - **JSON**: Posts, documentos, arrays
+ - **CSV**: Tabelas com dados estruturados
+ - **TXT**: Texto simples (divide por parágrafos)
+ - **PDF**: Extração de texto por página
+
+ **Limite:** 50MB por arquivo
+ """)
+
+ gr.Markdown("### 💡 Dicas")
+ gr.Markdown("""
+ 1. **JSON**: Pode ser lista ou objeto único
+ 2. **CSV**: Especifique a coluna com texto principal
+ 3. **TXT**: Será dividido por parágrafos vazios
+ 4. **PDF**: Cada página vira um documento
+
+ Após indexar, os dados ficam disponíveis no chat!
+ """)
+
+ gr.Markdown("### ⚙️ Estrutura Esperada (JSON)")
+ gr.Code(
+ value='''[
+ {
+ "text": "Conteúdo...",
+ "title": "Título",
+ "date": "2025-01-01",
+ "metadata": {...}
+ }
+]''',
+ language="json"
+ )
+
+ # Eventos
+ process_btn.click(
+ self.process_upload,
+ inputs=[
+ file_upload,
+ profile_name_input,
+ content_type_input, # 🆕 NOVO INPUT
+ text_column_input,
+ auto_index_checkbox
+ ],
+ outputs=[status_output, preview_output]
+ )
+
+ # 🆕 Sub-aba: Fontes Existentes
+ with gr.TabItem("📚 Fontes Indexadas"):
+ with gr.Row():
+ with gr.Column(scale=8):
+ sources_display = gr.HTML(value=self.generate_sources_html())
+
+ with gr.Column(scale=2):
+ gr.Markdown("### 🔧 Ações")
+
+ refresh_sources_btn = gr.Button(
+ "🔄 Atualizar",
+ variant="secondary",
+ size="lg"
+ )
+
+ gr.Markdown("---")
+ gr.Markdown("### 🗑️ Remover Fonte")
+
+ # 🔧 CORRIGIDO: Dropdown dinâmico
+ def get_sources_list():
+ """Retorna lista de fontes disponíveis."""
+ data = self.get_chromadb_sources()
+ if data['sources']:
+ return ["Selecione..."] + list(data['sources'].keys())
+ return ["Selecione..."]
+
+ source_to_delete = gr.Dropdown(
+ choices=get_sources_list(),
+ value="Selecione...",
+ label="Escolha a fonte",
+ interactive=True
+ )
+
+ delete_btn = gr.Button(
+ "🗑️ Remover Fonte",
+ variant="stop",
+ size="lg"
+ )
+
+ delete_status = gr.HTML()
+
+ gr.Markdown("""
+ ---
+ **⚠️ Atenção:**
+
+ Remover uma fonte é **irreversível**!
+ Todos os documentos dessa fonte serão deletados do ChromaDB.
+ """)
+
+ # 🔧 CORRIGIDO: Eventos com atualização correta
+
+ # Atualiza display E dropdown ao clicar em "Atualizar"
+ refresh_sources_btn.click(
+ fn=lambda: (
+ self.generate_sources_html(),
+ gr.update(choices=get_sources_list(), value="Selecione...")
+ ),
+ outputs=[sources_display, source_to_delete]
+ )
+
+ # 🔧 CORRIGIDO: Ao deletar, atualiza display + dropdown + limpa status
+ delete_btn.click(
+ fn=self.delete_source,
+ inputs=[source_to_delete],
+ outputs=[delete_status, sources_display]
+ ).then(
+ # Após deletar, atualiza dropdown e limpa seleção
+ fn=lambda: gr.update(
+ choices=get_sources_list(),
+ value="Selecione..."
+ ),
+ outputs=[source_to_delete]
+ )
+
+ # ===== ABA 5: DOCUMENTAÇÃO =====
with gr.TabItem("📖 Documentação"):
gr.HTML(f"""
@@ -1060,7 +2096,7 @@ def search_history(query):
💚 Dicas
-
+
- Use linguagem natural - não precisa ser exato
- Combine filtros de perfil com perguntas para resultados mais específicos
- Verifique o histórico para rever respostas anteriores
@@ -1172,51 +2208,304 @@ def launch(self, **kwargs):
app = self.create_interface()
app.launch(**kwargs)
+ def get_chromadb_sources(self) -> Dict[str, Any]:
+ """
+ Retorna informações sobre as fontes/arquivos no ChromaDB.
+
+ Returns:
+ Dict com estatísticas por fonte
+ """
+ try:
+ # Busca todos os documentos
+ if self.use_agent:
+ collection = self.agent.embedding_manager.collection
+ else:
+ collection = self.embedding_manager.collection
+
+ # Pega todos os documentos
+ results = collection.get(
+ limit=100000,
+ include=['metadatas']
+ )
+
+ if not results['ids']:
+ return {
+ 'total': 0,
+ 'sources': {},
+ 'error': None
+ }
+
+ # Agrupa por fonte/perfil
+ sources = {}
+ for metadata in results['metadatas']:
+ profile = metadata.get('profile', 'unknown')
+ content_type = metadata.get('content_type', 'instagram_post')
+
+ if profile not in sources:
+ sources[profile] = {
+ 'name': profile,
+ 'count': 0,
+ 'types': {},
+ 'oldest': None,
+ 'newest': None
+ }
+
+ sources[profile]['count'] += 1
+ sources[profile]['types'][content_type] = sources[profile]['types'].get(content_type, 0) + 1
+
+ # Atualiza datas
+ timestamp = metadata.get('timestamp')
+ if timestamp:
+ try:
+ from dateutil import parser as date_parser
+ dt = date_parser.parse(timestamp)
+
+ if sources[profile]['oldest'] is None or dt < sources[profile]['oldest']:
+ sources[profile]['oldest'] = dt
+
+ if sources[profile]['newest'] is None or dt > sources[profile]['newest']:
+ sources[profile]['newest'] = dt
+ except:
+ pass
+
+ return {
+ 'total': len(results['ids']),
+ 'sources': sources,
+ 'error': None
+ }
+
+ except Exception as e:
+ return {
+ 'total': 0,
+ 'sources': {},
+ 'error': str(e)
+ }
+
+ def generate_sources_html(self) -> str:
+ """
+ Gera HTML com lista de fontes/arquivos no ChromaDB.
+
+ Returns:
+ HTML formatado
+ """
+ data = self.get_chromadb_sources()
+
+ if data['error']:
+ return f"""
+
+
❌ Erro ao carregar fontes
+
{data['error']}
+
+ """
+
+ if data['total'] == 0:
+ return """
+
+
📭 Nenhum dado indexado
+
Faça upload de arquivos para começar!
+
+ """
+
+ html = f"""
+
+
+
📚 Fontes Indexadas
+
Total: {data['total']:,} documentos
+
+
+
+ """
+
+ # Cards por fonte
+ for source_name, source_data in sorted(data['sources'].items(), key=lambda x: x[1]['count'], reverse=True):
+ # Formata datas
+ oldest = source_data['oldest'].strftime('%d/%m/%Y') if source_data['oldest'] else "Desconhecida"
+ newest = source_data['newest'].strftime('%d/%m/%Y') if source_data['newest'] else "Desconhecida"
+
+ # Tipos de conteúdo
+ types_html = ""
+ for content_type, count in source_data['types'].items():
+ icon = {
+ 'instagram_post': '📷',
+ 'news': '📰',
+ 'custom': '📄'
+ }.get(content_type, '📄')
+
+ types_html += f"""
+
+ {icon} {content_type}: {count}
+
+ """
+
+ html += f"""
+
+
+
+
+
@{source_name}
+
+ 📊 {source_data['count']:,} documentos
+
+
+
+ {((source_data['count'] / data['total']) * 100):.1f}%
+
+
+
+
+ {types_html}
+
+
+
+
+ 📅 Mais antigo: {oldest}
+
+
+ 🆕 Mais recente: {newest}
+
+
+
+ """
+
+ html += """
+
+
+ """
+
+ return html
+
+ def delete_source(self, source_name: str) -> Tuple[str, str]:
+ """
+ Remove uma fonte/perfil do ChromaDB.
+
+ Args:
+ source_name: Nome da fonte a ser removida
+
+ Returns:
+ Tuple (status_html, sources_html_atualizado)
+ """
+ try:
+ if not source_name or source_name == "Selecione...":
+ return (
+ "⚠️ Selecione uma fonte para remover
",
+ self.generate_sources_html()
+ )
+
+ # Remove perfil do ChromaDB
+ if self.use_agent:
+ collection = self.agent.embedding_manager.collection
+ else:
+ collection = self.embedding_manager.collection
+
+ # Busca IDs da fonte
+ results = collection.get(
+ where={'profile': source_name},
+ limit=100000
+ )
+
+ if not results['ids']:
+ return (
+ f"⚠️ Fonte '{source_name}' não encontrada
",
+ self.generate_sources_html()
+ )
+
+ # Deleta documentos
+ collection.delete(ids=results['ids'])
+
+ # Atualiza stats
+ self._refresh_stats()
+
+ return (
+ f"✅ Fonte '@{source_name}' removida com sucesso! {len(results['ids'])} documentos deletados.
",
+ self.generate_sources_html()
+ )
+
+ except Exception as e:
+ return (
+ f"❌ Erro ao remover fonte: {str(e)}
",
+ self.generate_sources_html()
+ )
+
+
+# 🔧 ADICIONAR NO FINAL DO ARQUIVO (após a classe InstagramRAGApp)
-def main():
- """Função principal."""
+if __name__ == "__main__":
import argparse
- parser = argparse.ArgumentParser(description="Instagram RAG Chat App")
- parser.add_argument(
- "--embedding-model",
- default="mxbai-embed-large",
- help="Modelo Ollama para embeddings"
- )
- parser.add_argument(
- "--generation-model",
- default="qwen3:30b",
- help="Modelo Ollama para geração de respostas"
- )
- parser.add_argument(
- "--share",
- action="store_true",
- help="Criar link público do Gradio"
- )
- parser.add_argument(
- "--port",
- type=int,
- default=7860,
- help="Porta para a aplicação"
- )
+ # Parse de argumentos
+ parser = argparse.ArgumentParser(description="PING - UFF ANALYTICS")
+ parser.add_argument("--port", type=int, default=7860, help="Porta do servidor (padrão: 7860)")
+ parser.add_argument("--share", action="store_true", help="Criar link público compartilhável")
+ parser.add_argument("--embedding-model", type=str, default="mxbai-embed-large", help="Modelo de embeddings")
+ parser.add_argument("--generation-model", type=str, default="qwen3:30b", help="Modelo de geração")
+ parser.add_argument("--no-agent", action="store_true", help="Desabilita modo agente (usa RAG clássico)")
args = parser.parse_args()
+ print("\n" + "="*60)
+ print("🎓 PING - UFF ANALYTICS".center(60))
+ print("="*60)
+
# Inicializa aplicação
+ print("\n📦 Inicializando sistema...")
app = InstagramRAGApp(
embedding_model=args.embedding_model,
- generation_model=args.generation_model
+ generation_model=args.generation_model,
+ use_agent=not args.no_agent
)
+ print("\n🚀 Iniciando servidor Gradio...")
+ print(f" 🌐 Porta: {args.port}")
+ print(f" 🔗 URL: http://localhost:{args.port}")
+ if args.share:
+ print(" 🌍 Link público será gerado...")
+
+ print("\n" + "="*60)
+ print("✨ Aplicação pronta! Acesse no navegador.".center(60))
+ print("="*60 + "\n")
+
# Lança interface
- print(f"\n🌐 Iniciando interface web na porta {args.port}...")
- app.launch(
- server_name="0.0.0.0",
- server_port=args.port,
- share=args.share,
- inbrowser=True
- )
-
-
-if __name__ == "__main__":
- main()
+ try:
+ app.launch(
+ server_port=args.port,
+ share=args.share,
+ server_name="0.0.0.0", # Aceita conexões externas
+ show_error=True,
+ quiet=False
+ )
+ except KeyboardInterrupt:
+ print("\n\n👋 Encerrando aplicação...")
+ except Exception as e:
+ print(f"\n❌ Erro ao iniciar: {e}")
+ import traceback
+ traceback.print_exc()
\ No newline at end of file
diff --git a/chat_history.json b/chat_history.json
index 0fe8911..5e1c176 100644
--- a/chat_history.json
+++ b/chat_history.json
@@ -1,4 +1,88 @@
[
+ {
+ "timestamp": "2025-11-03T14:36:30.230575",
+ "question": "nos debates, Roberto salles é a favor ou contra o teletrabalho?",
+ "response": "## Posição de Roberto Salles sobre Teletrabalho nos Debates\n\n**Posição predominante:** Confortável/Favorável\n\n**Análise dos posts:**\n\n- **7 posts** mencionam especificamente \"30h/Teletrabalho\" com classificação \"confortavel\"\n- **Distribuição de escores nos posts sobre teletrabalho:**\n - Escore 3 (mais confortável): 2 posts\n - Escore 2: 3 posts \n - Escore 1: 2 posts\n\n**Posts por debate:**\n- **1º debate**: 1 post (escore 3, confiança média)\n- **2º debate**: 1 post (escore 2, confiança baixa)\n-",
+ "profile_filter": "Debate Roberto Salles, dceuff, noticias, reitor, vicereitor",
+ "posts_count": 20
+ },
+ {
+ "timestamp": "2025-11-03T14:33:53.099519",
+ "question": "O que roberto salles fala sobre Teletrabalho?",
+ "response": "Com base nos resultados de busca fornecidos, **não há nenhuma menção específica sobre Roberto Salles falando sobre teletrabalho**.\n\n## Contexto Encontrado sobre Roberto Salles\n\n**Período como reitor:** 2006-2014\n\n**Temas abordados nas notícias disponíveis:**\n\n### Gestão Universitária\n- **Expansão da UFF**: Meta de tornar a universidade a maior do Brasil, com crescimento de 5.000 para 10.500 vagas entre 2006-2014\n- **Obras e infraestrutura**: Reforma do Cine Arte UFF e construção de novos prédios",
+ "profile_filter": "Debate Roberto Salles, dceuff, noticias, reitor, vicereitor",
+ "posts_count": 30
+ },
+ {
+ "timestamp": "2025-11-03T14:31:49.123181",
+ "question": "qual a posição do roberto salles sobre Teletrabalho?",
+ "response": "## Posição de Roberto Salles sobre Teletrabalho\n\n### 📊 Análise dos Debates (2025)\n\n**Contexto**: Os dados são de debates realizados em 2025, onde Roberto Salles participou como debatedor/candidato, não como reitor.\n\n**Posição predominante**: **Confortável** com o tema do teletrabalho\n\n**Detalhes dos debates**:\n- **8 dos 10 trechos** foram classificados como \"confortável\" com o tema\n- **2 trechos** foram classificados como \"neutro\"\n- **Tópicos principais**: 30h/Teletrabalho, EAD/Remoto, Eleições/",
+ "profile_filter": "Debate Roberto Salles, dceuff, noticias, reitor, vicereitor",
+ "posts_count": 30
+ },
+ {
+ "timestamp": "2025-11-03T14:15:45.638352",
+ "question": "Quantas vezes roberto salles fala sobre Teletrabalho?",
+ "response": "Com base na análise das notícias fornecidas, **não há nenhuma menção a Roberto Salles falando sobre Teletrabalho** nos materiais consultados.\n\n## Período das Notícias Analisadas:\n- **2009-2014**: Período em que Roberto Salles foi reitor da UFF\n- **2018**: Quando foi candidato à reitoria (não eleito)\n\n## Contexto das Menções a Roberto Salles:\n\n**Como reitor (2006-2014):**\n- Gestão de obras e expansão da universidade\n- Posicionamento sobre Lei de Cotas (2012)\n- Parceria com prefeitura para Cine Ic",
+ "profile_filter": "dceuff, noticias, reitor, vicereitor",
+ "posts_count": 40
+ },
+ {
+ "timestamp": "2025-11-03T14:14:22.377947",
+ "question": "você tem acesso a esse arquivo, custom_data_20251103_140618_Debate_Roberto_Salles.json?",
+ "response": "Não consegui determinar como responder sua pergunta. Tente reformular.",
+ "profile_filter": "dceuff, noticias, reitor, vicereitor",
+ "posts_count": 0
+ },
+ {
+ "timestamp": "2025-11-03T14:12:38.060820",
+ "question": "No debate do roberto salles, o que o roberto salles fala sobre Teletrabalho?",
+ "response": "Com base nos resultados das buscas realizadas, **não foram encontradas menções específicas sobre Roberto Salles falando sobre teletrabalho** nos materiais consultados.\n\n## Contexto Encontrado sobre Roberto Salles:\n\n**Período como reitor (2006-2014):**\n- Foi reitor da UFF de 23/11/2006 a 18/11/2014\n- Durante sua gestão, apareceu em notícias sobre:\n - Expansão da universidade e aumento de vagas\n - Obras de infraestrutura no campus\n - Posicionamento sobre Lei de Cotas\n - Parceria para gestão do",
+ "profile_filter": "dceuff, noticias, reitor, vicereitor",
+ "posts_count": 30
+ },
+ {
+ "timestamp": "2025-11-03T14:11:15.654991",
+ "question": "o que o roberto salles fala sobre Teletrabalho?",
+ "response": "Com base nos resultados de busca fornecidos, **não há nenhuma menção sobre Roberto Salles falando sobre Teletrabalho** nas notícias disponíveis.\n\n## Período de atuação de Roberto Salles:\n- **Reitor da UFF**: 23 de novembro de 2006 até 18 de novembro de 2014\n- **Candidato em 2018**: Não foi eleito\n\n## Tópicos encontrados sobre Roberto Salles:\n- **Expansão da UFF** (Notícias 2, 6, 8, 9)\n- **Lei de Cotas** (Notícias 7, 8)\n- **Cine Arte UFF** (Notícias 4, 5, 6)\n- **Campus de Macaé** (Notícia 7)\n- **",
+ "profile_filter": "dceuff, noticias, reitor, vicereitor",
+ "posts_count": 30
+ },
+ {
+ "timestamp": "2025-11-03T14:09:43.816589",
+ "question": "qual é o nível de confiança do roberto salles no tópico transparência/orçamento?",
+ "response": "Com base nas notícias fornecidas, não há informações específicas sobre o **nível de confiança de Roberto Salles no tópico transparência/orçamento**. No entanto, podemos extrair alguns dados relevantes sobre sua gestão como reitor da UFF (2006-2014):\n\n## Contexto da Gestão de Roberto Salles (2006-2014)\n\n### **Investimentos e Obras**\n- **Expansão da UFF**: Sob sua gestão, a universidade passou de 5 mil vagas em 2006 para 10.500 vagas em 2014, com meta de ser a maior universidade do Brasil ([O Glob",
+ "profile_filter": "dceuff, noticias, reitor, vicereitor",
+ "posts_count": 30
+ },
+ {
+ "timestamp": "2025-11-03T11:31:05.693474",
+ "question": "Que documento é esse? ID: custom_18eeccfb331b49f6\nPerfil: custom_data\nTipo: custom_ingestion",
+ "response": "## Análise do Documento Solicitado\n\n**ID do documento:** custom_18eeccfb331b49f6 \n**Perfil:** custom_data \n**Tipo:** custom_ingestion \n\n**Dados do post relacionado:**\n- **Data de publicação:** 3 de novembro de 2025\n- **Engajamento:** 0 curtidas, 0 comentários\n- **Link:** Não disponível\n- **Conteúdo:** texto exemplo...\n\n**Observação:** Este é um documento de ingestão personalizada com dados de exemplo, não um post real do Instagram da UFF. O conteúdo aparece como texto de exemplo e não apresen",
+ "profile_filter": "dceuff, noticias, reitor, vicereitor",
+ "posts_count": 1
+ },
+ {
+ "timestamp": "2025-11-03T11:29:49.154109",
+ "question": "Mostre registros de custom_data",
+ "response": "# Análise de Posts do Instagram da UFF\n\n## Posts do Perfil @reitor (2024-2025)\n\n**Post mais recente:**\n- **Data:** 19 de agosto de 2025\n- **Curtidas:** 50\n- **Comentários:** 2\n- **Link:** https://www.instagram.com/p/DNiiXq2RB0L/\n- **Conteúdo:** Agradecimento ao reitor pela parceria com a Faperj para ciência, tecnologia e inovação\n\n**Outros posts:**\n- **29 de setembro de 2024** - 132 curtidas, 2 comentários\n - Evento \"Simplesmente Mulher\" da PROEX sobre cidadania e extensão\n - Link: https://www",
+ "profile_filter": "dceuff, noticias, reitor, vicereitor",
+ "posts_count": 10
+ },
+ {
+ "timestamp": "2025-10-31T10:52:02.032459",
+ "question": "Quero saber o top 3 de notícias negativas\n",
+ "response": "## Análise de Notícias Negativas - Instagram UFF\n\n**Resultado da Análise:** Nenhuma notícia negativa encontrada\n\n**Detalhamento:**\n- 🔍 **Posts analisados:** 0\n- 📊 **Distribuição:** 0 posts negativos identificados\n- ⏰ **Período:** Todos os perfis da UFF analisados\n\n**Conclusão:**\nNão foi possível identificar nenhuma notícia negativa nos posts do Instagram da UFF na análise realizada. A busca por conteúdo com essa característica não retornou resultados, indicando que não há posts classificados com",
+ "profile_filter": "dceuff, noticias, reitor, vicereitor",
+ "posts_count": 1
+ },
+ {
+ "timestamp": "2025-10-31T10:51:20.150888",
+ "question": "oi",
+ "response": "## Resumo das Estatísticas do Instagram da UFF\n\n**📊 Dados Gerais:**\n- **Total de posts analisados:** 2.437\n- **Curtidas totais:** 588.755\n- **Comentários totais:** 56.299\n- **Engajamento total:** 645.054\n\n**📈 Médias por Post:**\n- **Curtidas:** 241,59 por post\n- **Comentários:** 23,10 por post\n\n**🏆 Post com Maior Engajamento:**\n- **Link:** [https://www.instagram.com/p/C4tdlqvxKNU/](https://www.instagram.com/p/C4tdlqvxKNU/)\n- **Engajamento:** 17.991 interações\n\nEstes dados mostram um perfil ativo ",
+ "profile_filter": "dceuff, noticias, reitor, vicereitor",
+ "posts_count": 1
+ },
{
"timestamp": "2025-10-27T12:45:19.094458",
"question": "Posts sobre HUAP",
diff --git a/chroma_db/54d42dcf-5c95-4593-b8e5-f3cfade04121/data_level0.bin b/chroma_db/54d42dcf-5c95-4593-b8e5-f3cfade04121/data_level0.bin
index 98cb4f2..b660308 100644
Binary files a/chroma_db/54d42dcf-5c95-4593-b8e5-f3cfade04121/data_level0.bin and b/chroma_db/54d42dcf-5c95-4593-b8e5-f3cfade04121/data_level0.bin differ
diff --git a/chroma_db/54d42dcf-5c95-4593-b8e5-f3cfade04121/header.bin b/chroma_db/54d42dcf-5c95-4593-b8e5-f3cfade04121/header.bin
index be71b32..685f532 100644
Binary files a/chroma_db/54d42dcf-5c95-4593-b8e5-f3cfade04121/header.bin and b/chroma_db/54d42dcf-5c95-4593-b8e5-f3cfade04121/header.bin differ
diff --git a/chroma_db/54d42dcf-5c95-4593-b8e5-f3cfade04121/index_metadata.pickle b/chroma_db/54d42dcf-5c95-4593-b8e5-f3cfade04121/index_metadata.pickle
index e3c083a..64b6300 100644
Binary files a/chroma_db/54d42dcf-5c95-4593-b8e5-f3cfade04121/index_metadata.pickle and b/chroma_db/54d42dcf-5c95-4593-b8e5-f3cfade04121/index_metadata.pickle differ
diff --git a/chroma_db/54d42dcf-5c95-4593-b8e5-f3cfade04121/length.bin b/chroma_db/54d42dcf-5c95-4593-b8e5-f3cfade04121/length.bin
index 9de8698..bd46753 100644
Binary files a/chroma_db/54d42dcf-5c95-4593-b8e5-f3cfade04121/length.bin and b/chroma_db/54d42dcf-5c95-4593-b8e5-f3cfade04121/length.bin differ
diff --git a/chroma_db/54d42dcf-5c95-4593-b8e5-f3cfade04121/link_lists.bin b/chroma_db/54d42dcf-5c95-4593-b8e5-f3cfade04121/link_lists.bin
index 5e88b38..f501470 100644
Binary files a/chroma_db/54d42dcf-5c95-4593-b8e5-f3cfade04121/link_lists.bin and b/chroma_db/54d42dcf-5c95-4593-b8e5-f3cfade04121/link_lists.bin differ
diff --git a/chroma_db/chroma.sqlite3 b/chroma_db/chroma.sqlite3
index 0cf1dc2..615105d 100644
Binary files a/chroma_db/chroma.sqlite3 and b/chroma_db/chroma.sqlite3 differ
diff --git a/config.py b/config.py
index 7a0cce0..26c01a2 100644
--- a/config.py
+++ b/config.py
@@ -29,3 +29,16 @@
else:
print(f" - API Base: {OLLAMA_API_BASE}")
print(f" - Generation Model: {OLLAMA_GENERATION_MODEL}")
+
+# ========== CONFIGURAÇÕES DE ANÁLISE DE SENTIMENTO ==========
+
+# Modo padrão de análise
+# 'llm' = Usa IA (mais preciso, mais lento)
+# 'keywords' = Usa palavras-chave (mais rápido, menos preciso)
+DEFAULT_SENTIMENT_MODE = 'llm'
+
+# Tamanho do batch para análise LLM
+SENTIMENT_BATCH_SIZE = 50 # Posts por lote
+
+# Timeout para análise LLM (segundos)
+SENTIMENT_TIMEOUT = 300 # 5 minutos
diff --git a/dashboard_visualizer.py b/dashboard_visualizer.py
new file mode 100644
index 0000000..727fe00
--- /dev/null
+++ b/dashboard_visualizer.py
@@ -0,0 +1,925 @@
+"""
+Gerador de HTML/CSS para visualizações do dashboard.
+Cria gráficos e cards usando CSS puro (sem dependências JS).
+"""
+
+from typing import Dict, Any, List
+from datetime import datetime
+
+
+class DashboardVisualizer:
+ """Gerador de visualizações HTML para o dashboard."""
+
+ @staticmethod
+ def generate_dashboard_html(metrics: Dict[str, Any]) -> str:
+ """
+ Gera HTML completo do dashboard com métricas.
+
+ Args:
+ metrics: Dicionário de métricas do DashboardAnalytics
+
+ Returns:
+ HTML formatado
+ """
+ summary = metrics.get('summary', {})
+ posts_data = metrics.get('posts', {})
+ news_data = metrics.get('news', {})
+ sentiment_data = metrics.get('sentiment', {})
+ emerging_topics_data = metrics.get('emerging_topics', {}) # 🆕
+ recommendations_data = metrics.get('recommendations', {}) # 🆕
+
+ html = f"""
+
+
+
+
+ 📊 Dashboard de Análise
+
+
+ Atualizado em {datetime.now().strftime('%d/%m/%Y às %H:%M:%S')}
+
+
+
+
+ {DashboardVisualizer._generate_summary_cards(summary, posts_data, sentiment_data)}
+
+
+ {DashboardVisualizer._generate_sentiment_card(sentiment_data)}
+
+
+ {DashboardVisualizer._generate_emerging_topics_card(emerging_topics_data)}
+
+
+ {DashboardVisualizer._generate_engagement_charts(posts_data)}
+
+
+ {DashboardVisualizer._generate_profile_distribution(posts_data)}
+
+
+ {DashboardVisualizer._generate_top_posts(posts_data)}
+
+
+ {DashboardVisualizer._generate_news_section(news_data)}
+
+
+ {DashboardVisualizer._generate_policy_recommendations_card(recommendations_data)}
+
+ """
+
+ return html
+
+ @staticmethod
+ def _generate_summary_cards(summary: Dict, posts_data: Dict, sentiment_data: Dict) -> str:
+ """Gera cards de resumo."""
+ return f"""
+
+
+
+
📝 Total de Registros
+
{summary.get('total_records', 0):,}
+
+ {summary.get('posts_count', 0)} posts + {summary.get('news_count', 0)} notícias
+
+
+
+
+
+
❤️ Engajamento Total
+
{summary.get('total_engagement', 0):,}
+
+ Curtidas + Comentários
+
+
+
+
+
+
👍 Média de Curtidas
+
{posts_data.get('avg_likes', 0):.1f}
+
+ Por post
+
+
+
+
+
+
💬 Média de Comentários
+
{posts_data.get('avg_comments', 0):.1f}
+
+ Por post
+
+
+
+ """
+
+ @staticmethod
+ def _generate_sentiment_card(sentiment_data: Dict) -> str:
+ """🆕 Gera card de análise de sentimento agregado."""
+ if not sentiment_data or sentiment_data.get('total_analyzed', 0) == 0:
+ return ""
+
+ trend = sentiment_data.get('trend', 'neutral')
+
+ # Define cor e emoji baseado na tendência
+ if trend == 'positive':
+ gradient = 'linear-gradient(135deg, #4caf50 0%, #66bb6a 100%)'
+ emoji = '😊'
+ trend_text = 'Positiva'
+ trend_color = '#4caf50'
+ elif trend == 'negative':
+ gradient = 'linear-gradient(135deg, #f44336 0%, #e57373 100%)'
+ emoji = '😟'
+ trend_text = 'Negativa'
+ trend_color = '#f44336'
+ else:
+ gradient = 'linear-gradient(135deg, #9e9e9e 0%, #bdbdbd 100%)'
+ emoji = '😐'
+ trend_text = 'Neutra'
+ trend_color = '#9e9e9e'
+
+ pos_pct = sentiment_data.get('positive_pct', 0)
+ neg_pct = sentiment_data.get('negative_pct', 0)
+ neu_pct = sentiment_data.get('neutral_pct', 0)
+
+ total = sentiment_data.get('total_analyzed', 0)
+ pos_count = sentiment_data.get('positive', 0)
+ neg_count = sentiment_data.get('negative', 0)
+ neu_count = sentiment_data.get('neutral', 0)
+
+ profiles = sentiment_data.get('profiles', [])
+ profiles_text = ', '.join([f'@{p}' for p in profiles]) if profiles else 'Todas as fontes'
+
+ return f"""
+
+
+ 🎭 Análise de Sentimento do Período
+
+ {emoji} Tendência: {trend_text}
+
+
+
+
+
+
{emoji}
+
Sentimento {trend_text}
+
+ Baseado em {total:,} registros analisados
+
+
+ 📊 Fontes: {profiles_text}
+
+
+
+
+
+
📊 Distribuição Detalhada
+
+
+
+
+ ✅ Positivo
+
+ {pos_count} posts ({pos_pct}%)
+
+
+
+
+
+
+
+
+ ❌ Negativo
+
+ {neg_count} posts ({neg_pct}%)
+
+
+
+
+
+
+
+
+ ⚪ Neutro
+
+ {neu_count} posts ({neu_pct}%)
+
+
+
+
+
+
+
+
+ ℹ️ Metodologia: {sentiment_data.get('note', 'Análise de sentimento baseada em palavras-chave')}
+
+
+ """
+
+ @staticmethod
+ def _generate_emerging_topics_card(emerging_topics_data: Dict) -> str:
+ """🆕 Gera card com tópicos emergentes detectados."""
+ if not emerging_topics_data or emerging_topics_data.get('total_topics', 0) == 0:
+ return ""
+
+ topics = emerging_topics_data.get('topics', [])
+ total_analyzed = emerging_topics_data.get('total_posts_analyzed', 0)
+ total_unique_hashtags = emerging_topics_data.get('total_unique_hashtags', 0)
+ total_hashtag_occurrences = emerging_topics_data.get('total_hashtag_occurrences', 0)
+
+ # Gera lista de tópicos
+ topics_html = ""
+ for i, topic in enumerate(topics[:10], 1):
+ term = topic['term']
+ count = topic['count']
+ percentage = topic['percentage']
+ growth = topic.get('growth_indicator', 0)
+
+ # Define cor baseada no crescimento
+ if growth > 50:
+ trend_emoji = '🔥'
+ trend_text = 'Em alta'
+ trend_color = '#ff5722'
+ elif growth > 0:
+ trend_emoji = '📈'
+ trend_text = 'Crescendo'
+ trend_color = '#ff9800'
+ else:
+ trend_emoji = '📊'
+ trend_text = 'Estável'
+ trend_color = '#2196f3'
+
+ topics_html += f"""
+
+
+
+ {trend_emoji}
+
+ {term}
+
+
+ {trend_text}
+
+
+
+ Mencionado em {count} posts ({percentage}% do período)
+
+
+
+
+ """
+
+ # 🆕 SIMPLIFICADO: Top 5 Hashtags com design destacado
+ hashtags_html = ""
+ top_hashtags = emerging_topics_data.get('top_hashtags', [])
+
+ if top_hashtags and len(top_hashtags) > 0:
+ avg_hashtags_per_post = round(total_hashtag_occurrences / total_analyzed, 2) if total_analyzed > 0 else 0
+
+ hashtags_html = f"""
+
+
+
🏷️ Top 5 Hashtags
+
+
{total_unique_hashtags} hashtags únicas
+
{avg_hashtags_per_post} por post (média)
+
+
+
+
+
+ """
+
+ for i, hashtag in enumerate(top_hashtags, 1):
+ tag = hashtag['tag']
+ count = hashtag['count']
+ percentage = hashtag.get('percentage', 0)
+
+ # Cor do ranking (gradientes bonitos)
+ if i == 1:
+ rank_color = '#ffd700' # Ouro
+ rank_gradient = 'linear-gradient(135deg, #ffd700 0%, #ffed4e 100%)'
+ rank_emoji = '🥇'
+ elif i == 2:
+ rank_color = '#c0c0c0' # Prata
+ rank_gradient = 'linear-gradient(135deg, #c0c0c0 0%, #e0e0e0 100%)'
+ rank_emoji = '🥈'
+ elif i == 3:
+ rank_color = '#cd7f32' # Bronze
+ rank_gradient = 'linear-gradient(135deg, #cd7f32 0%, #d4a574 100%)'
+ rank_emoji = '🥉'
+ elif i == 4:
+ rank_color = '#667eea'
+ rank_gradient = 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'
+ rank_emoji = '#4'
+ else:
+ rank_color = '#2196f3'
+ rank_gradient = 'linear-gradient(135deg, #2196f3 0%, #1976d2 100%)'
+ rank_emoji = '#5'
+
+ hashtags_html += f"""
+
+
{rank_emoji}
+
+ #{tag}
+
+
+ {count}
+
+
+ menções ({percentage}%)
+
+
+ """
+
+ hashtags_html += """
+
+
+ """
+
+ return f"""
+
+
+ 🔍 Tópicos Emergentes
+
+ {total_analyzed:,} posts analisados
+
+
+
+
+
+ ℹ️ Sobre esta análise: Identificamos automaticamente os termos e temas mais mencionados nas legendas e hashtags dos posts no período selecionado, considerando frequência e contexto.
+
+
+
+ {topics_html}
+
+ {hashtags_html}
+
+ """
+
+ @staticmethod
+ def _generate_engagement_charts(posts_data: Dict) -> str:
+ """Gera gráfico de barras de engajamento."""
+ if not posts_data.get('by_profile'):
+ return ""
+
+ # Calcula valores máximos para escala
+ max_engagement = max(
+ [p['engagement'] for p in posts_data['by_profile'].values()],
+ default=1
+ )
+
+ bars_html = ""
+ for profile, data in sorted(
+ posts_data['by_profile'].items(),
+ key=lambda x: x[1]['engagement'],
+ reverse=True
+ ):
+ percentage = (data['engagement'] / max_engagement) * 100 if max_engagement > 0 else 0
+
+ bars_html += f"""
+
+
+ @{profile}
+
+ {data['engagement']:,} interações
+
+
+
+
+ {data['count']} posts
+
+
+
+ 👍 {data['likes']:,}
+ 💬 {data['comments']:,}
+ 📊 Média: {(data['engagement'] / data['count']):.1f}
+
+
+ """
+
+ return f"""
+
+
📈 Engajamento por Fonte
+ {bars_html}
+
+ """
+
+ @staticmethod
+ def _generate_profile_distribution(posts_data: Dict) -> str:
+ """Gera distribuição de posts por perfil."""
+ if not posts_data.get('by_profile'):
+ return ""
+
+ total_posts = posts_data.get('total', 1)
+
+ items_html = ""
+ for profile, data in sorted(
+ posts_data['by_profile'].items(),
+ key=lambda x: x[1]['count'],
+ reverse=True
+ ):
+ percentage = (data['count'] / total_posts) * 100 if total_posts > 0 else 0
+
+ items_html += f"""
+
+
+
@{profile}
+
+ {data['count']} posts ({percentage:.1f}%)
+
+
+
+
+ {data['engagement']:,}
+
+
+ engajamento
+
+
+
+ """
+
+ return f"""
+
+
📊 Distribuição por Perfil
+ {items_html}
+
+ """
+
+ @staticmethod
+ def _generate_top_posts(posts_data: Dict) -> str:
+ """Gera lista de top posts."""
+ top_posts = posts_data.get('top_by_engagement', [])[:5]
+
+ if not top_posts:
+ return ""
+
+ posts_html = ""
+ for i, post in enumerate(top_posts, 1):
+ posts_html += f"""
+
+
+
+
+ #{i}
+
+
+ @{post['profile']}
+
+
+
+
+ {post['engagement']:,}
+
+
+ 👍 {post['likes']} | 💬 {post['comments']}
+
+
+
+
+ {post['caption']}
+
+
+ Ver post →
+
+
+ """
+
+ return f"""
+
+
🏆 Top 5 Posts por Engajamento
+ {posts_html}
+
+ """
+
+ @staticmethod
+ def _generate_news_section(news_data: Dict) -> str:
+ """Gera seção de notícias."""
+ if not news_data.get('total'):
+ return ""
+
+ publishers = news_data.get('by_publisher', {})
+
+ pubs_html = ""
+ for pub, count in sorted(publishers.items(), key=lambda x: x[1], reverse=True)[:10]:
+ pubs_html += f"""
+
+ {pub}
+ {count}
+
+ """
+
+ return f"""
+
+
📰 Notícias no Período
+
+
+ {news_data['total']:,}
+
+
+ notícias indexadas
+
+
+
+ Top Publishers
+
+ {pubs_html}
+
+ """
+
+ @staticmethod
+ def _generate_policy_recommendations_card(recommendations: Dict) -> str:
+ """🆕 Gera card com recomendações de políticas."""
+
+ # 🔧 Verifica se há recomendações na lista
+ recs_list = recommendations.get('recommendations', [])
+ if not recs_list or len(recs_list) == 0:
+ return """
+
+
⚠️ Sem Recomendações
+
Não há dados suficientes para gerar recomendações.
+
+ """
+
+ # Resumo do sentimento
+ sentiment = recommendations.get('sentiment_analysis', {})
+ engagement = recommendations.get('engagement_trends', {})
+
+ # Cabeçalho com estatísticas
+ sentiment_html = f"""
+
+
+
😊
+
{sentiment.get('positive_pct', 0):.1f}%
+
Positivo
+
+
+
😐
+
{sentiment.get('neutral_pct', 0):.1f}%
+
Neutro
+
+
+
😟
+
{sentiment.get('negative_pct', 0):.1f}%
+
Negativo
+
+
+ """
+
+ # Recomendações
+ rec_html = ""
+ priority_icons = {
+ 'alta': '🔴',
+ 'média': '🟡',
+ 'baixa': '🟢'
+ }
+
+ priority_colors = {
+ 'alta': '#f44336',
+ 'média': '#ff9800',
+ 'baixa': '#4caf50'
+ }
+
+ for i, rec in enumerate(recs_list, 1):
+ priority = rec.get('priority', 'média').lower()
+ icon = priority_icons.get(priority, '⚪')
+ color = priority_colors.get(priority, '#9e9e9e')
+
+ rec_html += f"""
+
+
+
+ {icon} {i}. {rec.get('area', 'Área não especificada')}
+
+
+ {priority.upper()}
+
+
+
+
+
📋 Ação Recomendada:
+
{rec.get('action', 'Não especificado')}
+
+
🎯 Impacto Esperado:
+
{rec.get('expected_impact', 'Não especificado')}
+
+ {f"
💡 Justificativa:
{rec.get('reasoning', '')}
" if rec.get('reasoning') else ''}
+
+
+
+ ⏱️ Prazo: {rec.get('implementation_time', 'N/A')}
+
+
+ 👤 Responsável: {rec.get('responsible', 'N/A')}
+
+
+
+
+ """
+
+ return f"""
+
+
🔮 RECOMENDAÇÕES DE POLÍTICAS PÚBLICAS
+
+ Análise baseada em {sentiment.get('total_analyzed', 0)} registros |
+ Tendência: {engagement.get('recent_trend', 'N/A').title()}
+
+
+
+
+
� Panorama de Sentimento
+ {sentiment_html}
+
+ {sentiment.get('note', '')}
+
+
+
+
+
💡 Recomendações de Ações ({len(recs_list)})
+
+ As seguintes ações foram recomendadas com base na análise completa do conteúdo das legendas e comentários:
+
+ {rec_html}
+
+
+
+
+ ℹ️ Nota Metodológica: Estas recomendações foram geradas por IA (DeepSeek Chat)
+ através da análise qualitativa completa das legendas e comentários dos posts, considerando contexto,
+ temas recorrentes e preocupações da comunidade acadêmica. Recomenda-se avaliação criteriosa pela gestão
+ antes da implementação.
+
+
+ """
+
+
+def main():
+ """Função de teste."""
+ print("=== Testando Dashboard Visualizer ===\n")
+
+ # Mock data para teste
+ mock_metrics = {
+ 'summary': {
+ 'total_records': 2500,
+ 'posts_count': 2400,
+ 'news_count': 100,
+ 'total_engagement': 150000,
+ 'avg_engagement_per_post': 62.5
+ },
+ 'posts': {
+ 'total': 2400,
+ 'total_likes': 120000,
+ 'total_comments': 30000,
+ 'total_engagement': 150000,
+ 'avg_likes': 50.0,
+ 'avg_comments': 12.5,
+ 'avg_engagement': 62.5,
+ 'top_by_engagement': [
+ {
+ 'profile': 'dceuff',
+ 'likes': 500,
+ 'comments': 120,
+ 'engagement': 620,
+ 'url': 'https://instagram.com/p/test1',
+ 'caption': 'Post de teste sobre greve estudantil...'
+ }
+ ],
+ 'by_profile': {
+ 'dceuff': {'count': 1500, 'likes': 75000, 'comments': 18000, 'engagement': 93000},
+ 'reitor': {'count': 600, 'likes': 30000, 'comments': 8000, 'engagement': 38000},
+ 'vicereitor': {'count': 300, 'likes': 15000, 'comments': 4000, 'engagement': 19000}
+ }
+ },
+ 'news': {
+ 'total': 100,
+ 'by_publisher': {
+ 'BBC Brasil': 30,
+ 'G1': 25,
+ 'Folha': 20,
+ 'O Globo': 15,
+ 'Estadão': 10
+ }
+ },
+ 'sentiment': { # 🆕 Mock de sentimento
+ 'total_analyzed': 100,
+ 'positive': 35,
+ 'negative': 45,
+ 'neutral': 20,
+ 'positive_pct': 35.0,
+ 'negative_pct': 45.0,
+ 'neutral_pct': 20.0,
+ 'trend': 'negative',
+ 'profiles': ['dceuff', 'reitor'],
+ 'note': 'Análise baseada em amostra de 100 registros'
+ },
+ 'emerging_topics': { # 🆕 Mock de tópicos emergentes
+ 'total_topics': 8,
+ 'total_posts_analyzed': 2400,
+ 'topics': [
+ {'term': 'greve', 'count': 156, 'percentage': 6.5, 'growth_indicator': 75},
+ {'term': 'HUAP', 'count': 134, 'percentage': 5.6, 'growth_indicator': 60},
+ {'term': 'educação', 'count': 98, 'percentage': 4.1, 'growth_indicator': 45},
+ {'term': 'reitoria', 'count': 87, 'percentage': 3.6, 'growth_indicator': 30},
+ {'term': 'estudantes', 'count': 76, 'percentage': 3.2, 'growth_indicator': 20},
+ {'term': 'universidade', 'count': 65, 'percentage': 2.7, 'growth_indicator': 10},
+ {'term': 'campus', 'count': 54, 'percentage': 2.3, 'growth_indicator': 5},
+ {'term': 'pesquisa', 'count': 43, 'percentage': 1.8, 'growth_indicator': 0}
+ ],
+ 'top_hashtags': [
+ {'tag': 'UFF', 'count': 245},
+ {'tag': 'GreveNaUFF', 'count': 156},
+ {'tag': 'HUAP', 'count': 134},
+ {'tag': 'EducaçãoPública', 'count': 98},
+ {'tag': 'UniversidadePública', 'count': 87},
+ {'tag': 'DCE', 'count': 76},
+ {'tag': 'MovimentoEstudantil', 'count': 65},
+ {'tag': 'Niterói', 'count': 54},
+ {'tag': 'ForaReitor', 'count': 43},
+ {'tag': 'DefendaUFF', 'count': 38}
+ ]
+ },
+ 'recommendations': { # 🆕 Mock de recomendações
+ 'has_recommendations': True,
+ 'summary': 'Identificamos algumas áreas críticas e recomendamos ações específicas.',
+ 'sentiment_data': {
+ 'positive_pct': 35.0,
+ 'negative_pct': 45.0,
+ 'neutral_pct': 20.0
+ },
+ 'critical_areas': [
+ {
+ 'area': 'Comunicação',
+ 'frequency': 'alta',
+ 'examples': ['Falta de clareza nas informações', 'Pouca transparência nas decisões']
+ },
+ {
+ 'area': 'Infraestrutura',
+ 'frequency': 'média',
+ 'examples': ['Problemas recorrentes de acesso', 'Baixa qualidade das instalações']
+ }
+ ],
+ 'recommendations': [
+ {
+ 'area': 'Comunicação',
+ 'priority': 'alta',
+ 'action': 'Melhorar a clareza e frequência das comunicações oficiais.',
+ 'expected_impact': 'Aumentar a confiança e engajamento da comunidade.',
+ 'implementation_time': 'Curto prazo',
+ 'responsible': 'Equipe de Comunicação'
+ },
+ {
+ 'area': 'Infraestrutura',
+ 'priority': 'média',
+ 'action': 'Realizar manutenção e melhorias nas instalações críticas.',
+ 'expected_impact': 'Reduzir queixas e melhorar a satisfação geral.',
+ 'implementation_time': 'Médio prazo'
+ }
+ ],
+ 'positive_aspects': [
+ 'Aumento no engajamento em posts positivos.',
+ 'Crescimento no número de seguidores.'
+ ],
+ 'general_observations': 'As recomendações foram geradas com base em análises de sentimento e devem ser avaliadas no contexto institucional.'
+ }
+ }
+
+ html = DashboardVisualizer.generate_dashboard_html(mock_metrics)
+
+ # Salva para teste visual
+ with open('test_dashboard_with_sentiment.html', 'w', encoding='utf-8') as f:
+ f.write(f"""
+
+
+
+
+
+
+
+ {html}
+
+
+ """)
+
+ print("✅ HTML de teste gerado: test_dashboard_with_sentiment.html")
+
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/data/debate_roberto_salles_20251103_165202_Debate_Roberto_Salles.json b/data/debate_roberto_salles_20251103_165202_Debate_Roberto_Salles.json
new file mode 100644
index 0000000..67547de
--- /dev/null
+++ b/data/debate_roberto_salles_20251103_165202_Debate_Roberto_Salles.json
@@ -0,0 +1,4204 @@
+[
+ {
+ "id_global": 1,
+ "fonte": "1o_debate",
+ "id_local": 1,
+ "timecode": "00:08:43",
+ "topicos": "ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto Salleschamada Bolsa de Trabalho, a única bolsa existente naquela época. Tive a oportunidade de chegar a reitor da universidade, de 2006 a 2014, época do ReUni, o maior programa de... A estruturação e expansão do país foi o maior projeto, abraçamos com toda a força a causa. Tivemos a oportunidade de levar a UFF para oito municípios do estado do Rio de Janeiro, inclusive aqui em Campos."
+ },
+ {
+ "id_global": 2,
+ "fonte": "1o_debate",
+ "id_local": 2,
+ "timecode": "00:09:19",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesNa época, nós tínhamos um curso de serviço social excelente durante 40 anos. Junto com a comunidade, tivemos a oportunidade de criar mais cinco cursos. Com licenciatura e bacharelado, são oito cursos, dois cursos estritos centros. E tivemos a oportunidade de, junto com a comunidade, sempre junto, ouvindo,"
+ },
+ {
+ "id_global": 3,
+ "fonte": "1o_debate",
+ "id_local": 3,
+ "timecode": "00:09:52",
+ "topicos": "ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallesadquirir aquele tempo. Terreno da rede ferroviária federal, a pedido da comunidade, depois de mais de dois anos. De tramitação, iniciamos a obra. Quero dizer que a chapa 3, Roberto Salles e Isabel, estamos determinados a terminar os dois blocos de prédios, se não for terminado até uma determinada data, no encerramento do reitor,"
+ },
+ {
+ "id_global": 4,
+ "fonte": "1o_debate",
+ "id_local": 4,
+ "timecode": "00:10:23",
+ "topicos": "Cultura/Cinema",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallese vamos avançar nas políticas sociais. Vamos implantar o que foi iniciado no projeto inicial, inclusive tendo um bandejão, e também a parte destinada ao galpão cultural e de artes. Agora eu passo para a professora Isabel."
+ },
+ {
+ "id_global": 5,
+ "fonte": "1o_debate",
+ "id_local": 5,
+ "timecode": "00:34:51",
+ "topicos": "ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesA Universidade Federal Fluminense cresceu muito de 2006 a 2014 por reunião. Cresceu o número de professores, cresceu o número de técnico-administrativo, dobrou o número de estudantes, multiplicou por quatro a pós-graduação. Então, está na hora da Universidade Federal Fluminense fazer uma statuinte. A statuinte é importante para rever todo o conceito de universidade, todas as regras,"
+ },
+ {
+ "id_global": 6,
+ "fonte": "1o_debate",
+ "id_local": 6,
+ "timecode": "00:35:23",
+ "topicos": "Governança/PDI",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallestodas as normas. Vejam bem, o próprio regimento geral das consultas eleitorais é de 1997 e hoje já, houve uma mudança na lei de escolha de reitores. Foi falado aqui do PDI, o Plano de Desenvolvimento Institucional, que é obrigatório nas universidades públicas e privadas. E é no PDI, com uma discussão ampla, que todos os segmentos podem participar."
+ },
+ {
+ "id_global": 7,
+ "fonte": "1o_debate",
+ "id_local": 7,
+ "timecode": "00:35:58",
+ "topicos": "Transparência/Orçamento",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesParticipar democraticamente. para priorizar os recursos, como no orçamento participativo. Então, o que nós estamos precisando? Precisamos levar a sério nosso plano de desenvolvimento institucional. Isso é fundamental. E aí todos saberão qual é a quantidade de recursos que nós temos e como aplicar e da melhor forma. Porque existem prioridades e prioridades."
+ },
+ {
+ "id_global": 8,
+ "fonte": "1o_debate",
+ "id_local": 8,
+ "timecode": "00:36:30",
+ "topicos": "Transparência/Orçamento",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEntão, nós temos que estabelecer. Não basta nós termos um aluno passando para a universidade pública. Nós precisamos fazer esse aluno se manter e se formar. Isso também vai ser importante lá na frente, na matriz orçamentária da universidade. Porque é medida pela taxa de sucesso. Número de alunos que entram na universidade e número de... alunos que se formam. Por isso que se faz necessário o incremento da política social."
+ },
+ {
+ "id_global": 9,
+ "fonte": "1o_debate",
+ "id_local": 9,
+ "timecode": "00:37:05",
+ "topicos": "Governança/PDI",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto Sallesdentro da universidade. Então, eu acho que nós temos dois caminhos, professor Wilson. Um é através de uma nova estatuinte para renovar, modernizar nossos estatutos e regimentos. E a segunda forma é valorizar o plano de desenvolvimento institucional da Universidade Federal Fluminense. Só assim, todos vão poder dizer quais são as prioridades da nossa universidade."
+ },
+ {
+ "id_global": 10,
+ "fonte": "1o_debate",
+ "id_local": 10,
+ "timecode": "00:39:50",
+ "topicos": "ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesHouve um avanço muito grande na ida da direção contrária. Porque antes as pessoas que moravam no município... Os municípios tinham que estudar lá em Niterói. Com o Reúne fizemos o caminho inverso, a universidade chegou nos municípios. Agora, precisamos melhorar essa relação. Nós fazíamos a reitoria itinerante, era uma forma de trazer toda a equipe de tempos em tempos."
+ },
+ {
+ "id_global": 11,
+ "fonte": "1o_debate",
+ "id_local": 11,
+ "timecode": "00:40:20",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallese fiz várias vezes aqui em Campos, isso aí pode perguntar a vários professores e técnicos administrativos que já estão com tempo aqui. Agora, outra questão também é o sentimento de pertencimento, que tem que voltar realmente na nossa Universidade Federal Fluminense. Então, temos que estreitar essa distância entre as unidades fora de sede e a estrutura lá da universidade. Então, temos que criar alguma coisa para encurtar esse caminho."
+ },
+ {
+ "id_global": 12,
+ "fonte": "1o_debate",
+ "id_local": 12,
+ "timecode": "00:42:02",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesPerguntar para a Chapa 1, qual a visão deles em relação ao ensino e educação à distância? Qual a importância e o que a gestão tem feito em relação a isso? Três minutos."
+ },
+ {
+ "id_global": 13,
+ "fonte": "1o_debate",
+ "id_local": 13,
+ "timecode": "00:45:31",
+ "topicos": "EAD/Remoto",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesNa verdade, tanto a Universidade Aberta do Brasil, que é uma parceria com o MEC, com o governo federal, e na nossa gestão, nós demos um impulso muito forte para a formação, principalmente, de professores em vários estados do Brasil. Pouca gente sabe, mas a UFF está presente em vários estados do Brasil, através da Universidade... aberta do Brasil. E no caso do CEDERJ, um convênio com o governo do Estado, em que."
+ },
+ {
+ "id_global": 14,
+ "fonte": "1o_debate",
+ "id_local": 14,
+ "timecode": "00:46:08",
+ "topicos": "EAD/Remoto",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Salleshá uma parceria com as universidades, também é uma modalidade muito importante para levar a educação, com o nome das universidades federais, para o interior do Estado do Rio de Janeiro. Facilita muito a vida das pessoas ter acesso a esses cursos, porque às vezes não pode nem se deslocar do local. E tem o ensino à distância, que é muito diferente do que nós tivemos aqui, que na verdade agora com a pandemia, que foi o ensino remoto. O."
+ },
+ {
+ "id_global": 15,
+ "fonte": "1o_debate",
+ "id_local": 15,
+ "timecode": "00:46:44",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesensino à distância precisa de toda uma tecnologia e precisa realmente de equipamentos e material para entrega, para poder os alunos terem acesso. Muito diferente. do que nós tivemos agora, mas a pandemia modificou tudo e nós temos que usar todas as ferramentas necessárias, mas a UFF sempre foi muito forte em termos de ensino à distância através da parceria com o governo federal e o governo estadual, tanto na Universidade."
+ },
+ {
+ "id_global": 16,
+ "fonte": "1o_debate",
+ "id_local": 16,
+ "timecode": "00:47:19",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesAberta do Brasil como no SEDER."
+ },
+ {
+ "id_global": 17,
+ "fonte": "1o_debate",
+ "id_local": 17,
+ "timecode": "00:48:33",
+ "topicos": "Cultura/Cinema|EAD/Remoto",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "Speaker 1Nesse momento, a chapa 1, obrigatoriamente, vai precisar fazer uma pergunta. A chapa 3, cujo tema vai ser sorteado agora. Políticas de produção artística cultural."
+ },
+ {
+ "id_global": 18,
+ "fonte": "1o_debate",
+ "id_local": 18,
+ "timecode": "00:49:01",
+ "topicos": "Cultura/Cinema",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Antônio ClaudioBom, quando se fala em políticas, é importante que se identifique atores, meios e na busca de resultados. A Universidade Federal Fluminense tem uma tradição muito grande, uma universidade sempre voltada à produção cultural, não apenas uma produção cultural que já seria de valor clássica, mas aquela relacionada à formação. Então, nós temos exemplo aqui em Campos, por exemplo, o Galpão Cultural, que há muitos anos é desejado."
+ },
+ {
+ "id_global": 19,
+ "fonte": "1o_debate",
+ "id_local": 19,
+ "timecode": "00:49:35",
+ "topicos": "Cultura/Cinema",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Antônio Claudiocomo um polo irradiador de produção cultural relacionado à região. Nós agora que estamos concluindo as duas torres, inclusive articulado com a direção da unidade, já fizemos a limpa do Galpão, já está reativada a comissão, inclusive com a perspectiva histórica. Então, gostaríamos de saber, da chapa 3, quais são as características da política, de uma forma ou outra, E produção artística e cultural da Chapa."
+ },
+ {
+ "id_global": 20,
+ "fonte": "1o_debate",
+ "id_local": 20,
+ "timecode": "00:50:02",
+ "topicos": "Cultura/Cinema|ReUni/Infra",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesTrês minutos. Bom, queria lembrar a todos que a Universidade Federal Fluminense não se caracteriza por uma universidade de ensino, pesquisa, extensão e, como consequência, assistência. Também nós temos que ter um pensamento voltado para a cultura e para as artes. E dentro do projeto Reúne, não esquecemos dessa parte. Nós tivemos a oportunidade de fazer um cinema novo na reitoria,"
+ },
+ {
+ "id_global": 21,
+ "fonte": "1o_debate",
+ "id_local": 21,
+ "timecode": "00:50:38",
+ "topicos": "Cultura/Cinema",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallessuper equipado, porque a população da UFF de Niterói, merece um equipamento cultural igual àquele, com a reforma do teatro e centro de arte. Mas a cultura também deve ser vista. Abrangendo toda a universidade e por isso que com o projeto das duas torres, falado aqui, que são projetos idealizados de sete andares cada bloco, foi pensado justamente no espaço, não só para o bandejão, como também para a expressão, aqui está o projeto Calpão Cultural, mas para a expressão artística e cultural."
+ },
+ {
+ "id_global": 22,
+ "fonte": "1o_debate",
+ "id_local": 22,
+ "timecode": "00:51:30",
+ "topicos": "Cultura/Cinema|ReUni/Infra",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEntão nós temos que estimular isso tudo. E lembro também que através de um pedido da comunidade de Niterói, à época do Reúne, não tínhamos expandido ainda, eu estive numa audiência pública na Câmara Municipal de Niterói e lá foi feito um apelo para que não deixasse o cinema Icaraí. Se transformar em mais um prédio."
+ },
+ {
+ "id_global": 23,
+ "fonte": "1o_debate",
+ "id_local": 23,
+ "timecode": "00:52:03",
+ "topicos": "Cultura/Cinema|ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesE tivemos com o ministro Fernando Haddad uma relação sempre de proximidade. Ele sempre entendeu que a Universidade Federal Fluminense fez o maior projeto de reestruturação e expansão e extra-orçamentariamente destinou uma parte do recurso para comprar o cinema em Caraí para transformar junto com o projeto arquitetônico da reitoria arte decor e transformar ali no ambiente cultural múltiplo."
+ },
+ {
+ "id_global": 24,
+ "fonte": "1o_debate",
+ "id_local": 24,
+ "timecode": "00:52:38",
+ "topicos": "Cultura/Cinema",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesque nós iríamos ter desde a apresentação de balé, da orquestra a apresentação de shows. Então ali foi realmente um ganho muito grande para a cultura da nossa Universidade Federal Fluminense, e para a cultura do estado do Rio de Janeiro como um todo. Mas infelizmente, desde a... Naquela época da compra e depois de passar para a propriedade da UFF, até agora, nada aconteceu e nós, ao retornarmos, vamos..."
+ },
+ {
+ "id_global": 25,
+ "fonte": "1o_debate",
+ "id_local": 25,
+ "timecode": "00:55:24",
+ "topicos": "Cultura/Cinema",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesUm minuto. Eu acho que o reitor esqueceu que o cinema em Caraí não foi abandonado, foi feito um projeto básico executivo. E tanto que o reitor que me sucedeu, que ele foi vice, ele se comprometeu, é só colocar no Google, se comprometeu a priorizar o término daquele complexo cultural do cinema em Caraí."
+ },
+ {
+ "id_global": 26,
+ "fonte": "1o_debate",
+ "id_local": 26,
+ "timecode": "00:55:57",
+ "topicos": "Cultura/Cinema|ReUni/Infra",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesQuero dizer claramente que... E nós colocamos no projeto, quando idealizamos aqui as duas torres, os dois prédios, nós idealizamos espaço também para a cultura. E estamos abraçando aqui o projeto do Galpão Cultural. Isso aqui não iremos abrir mão ou qualquer outra forma de expressão cultural dentro da Universidade Federal Fluminense. Então, esse é o nosso compromisso."
+ },
+ {
+ "id_global": 27,
+ "fonte": "1o_debate",
+ "id_local": 27,
+ "timecode": "00:57:04",
+ "topicos": "Transparência/Orçamento",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesGostaria de perguntar a Chapa 2, na visão de vocês, quais são os mecanismos que têm sido usados em relação à prestação de contas e divulgação do resultado, em especial na pandemia."
+ },
+ {
+ "id_global": 28,
+ "fonte": "1o_debate",
+ "id_local": 28,
+ "timecode": "01:00:53",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesBom, é verdade, sim, que houve uma redução do repasso de recursos. para as universidades. Isso é fato. Se eu não falho a memória, nós chegamos a ter um custeio, em 2014, quase 240 milhões. Mas, considerando que teve uma diminuição em dois anos de pandemia, nós temos que considerar também que, durante a pandemia, não tivemos gasto com material de ensino, que é caro, em especial para a área de saúde, não tivemos despesa com bandejão,"
+ },
+ {
+ "id_global": 29,
+ "fonte": "1o_debate",
+ "id_local": 29,
+ "timecode": "01:01:34",
+ "topicos": "Mobilidade/BuzUFF",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesnão tivemos despesa com combustível do BuzUFF, não tivemos despesa com água, ou pouca, claro que tivemos, mas pouca. Em tese, deveríamos ter também economia na questão da energia, e devíamos ter nos preparado esses dois anos. principalmente que nós temos uma frota, por exemplo, de ônibus que foram compradas há mais de 10 anos,"
+ },
+ {
+ "id_global": 30,
+ "fonte": "1o_debate",
+ "id_local": 30,
+ "timecode": "01:02:08",
+ "topicos": "Geral",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesos aparelhos de ar-condicionado que ficaram algum tempo parados durante a pandemia e também a questão dos botejões de um modo geral. Então, devíamos ter nos preparado para poder evitar qualquer contratempo nesse reinício. Agora, eu, inclusive, fiz a pergunta no Conselho Universitário sobre o quanto foi de economia."
+ },
+ {
+ "id_global": 31,
+ "fonte": "1o_debate",
+ "id_local": 31,
+ "timecode": "01:02:39",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesO reitor falou de um número global, não discriminou. Eu acho que isso é importante, sim, que durante esse tempo se coloque claramente o que foi economizado."
+ },
+ {
+ "id_global": 32,
+ "fonte": "1o_debate",
+ "id_local": 32,
+ "timecode": "01:17:20",
+ "topicos": "ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "Speaker 1A Patrícia quer que leia de novo. A pergunta é a seguinte, ao que teve destacado protagonismo nacional durante a pandemia no seu processo de expansão, concluindo projetos até então estagnados em Campos dos Goitacazes, quais serão as novas ações em relação à conclusão do novo polo e em relação ao nosso corpo docente administrativo? Professor Crisóstomo Lima, Departamento de Psicologia."
+ },
+ {
+ "id_global": 33,
+ "fonte": "1o_debate",
+ "id_local": 33,
+ "timecode": "01:17:50",
+ "topicos": "ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEu só queria discordar um pouco do que foi comentado. O que foi colocado afirmativo da estagnação. Na verdade, foram entregues 25 prédios, 140 reformas. A UFF praticamente dobrou de tamanho em área física. Foram acrescentadas mais 180 mil metros quadrados à área que tinha 50 anos, 240 mil metros quadrados. Foram deixadas seis obras, que não terminaram por vários motivos,"
+ },
+ {
+ "id_global": 34,
+ "fonte": "1o_debate",
+ "id_local": 34,
+ "timecode": "01:18:22",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesque não têm nada a ver com a pandemia. São oito anos após a saída, e, obviamente, eu, particularmente, esperava mais. Agora, a saída realmente são parcerias também, para poder minimizar a questão orçamentária, com todas as prefeituras onde a UFF se faz presente. E aqui foi feita uma bela parceria da comunidade aqui, com os deputados, inclusive o atual prefeito,"
+ },
+ {
+ "id_global": 35,
+ "fonte": "1o_debate",
+ "id_local": 35,
+ "timecode": "01:18:53",
+ "topicos": "Acessibilidade|Cultura/Cinema|Mobilidade/BuzUFF",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallesque colocou os recursos e, obviamente, que em dois anos para cá, o projeto... O projeto da término do prédio reiniciou e nós estamos torcendo para que termine. Agora, nós vamos fazer o que fizemos anteriormente, colocar em funcionamento, pegar o espaço do bandejão, construir o projeto aqui multicultural. Então, nós vamos avançar, assim como renovar a frota de BuzUFF, porque não tem nem acessibilidade."
+ },
+ {
+ "id_global": 36,
+ "fonte": "1o_debate",
+ "id_local": 36,
+ "timecode": "01:19:28",
+ "topicos": "Mobilidade/BuzUFF|ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesSão ônibus bem antigos e que precisam ser realmente trocados a frota para poder circular. Isso é muito importante para todos os lugares que a UFF faz presente, não só por causa da mobilidade, também como segurança. Então, nós vamos intensificar esses avanços, não só no término das obras aqui, como também nas outras."
+ },
+ {
+ "id_global": 37,
+ "fonte": "1o_debate",
+ "id_local": 37,
+ "timecode": "01:19:58",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEm outras políticas. Então, pesquisa, pós-graduação e inovação tem que ser incrementada na universidade. A universidade precisa avançar em relação às outras instituições. Isso é fundamental. Então, é isso que nós temos que fazer. É procurar não só cobrar do governo federal, que tem que dar para a universidade, para as universidades, assim como também as parcerias, formando alguns fundos, inclusive, para a parte social."
+ },
+ {
+ "id_global": 38,
+ "fonte": "1o_debate",
+ "id_local": 38,
+ "timecode": "01:20:31",
+ "topicos": "Acessibilidade|EAD/Remoto",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesIsso é fundamental, senão o aluno não consegue se manter na universidade. E também temos que nos preocupar com a sustentabilidade e a inclusão digital, fundamental nesse momento de pandemia. E nada vai ser como antes, obviamente. Então, temos que usar todos os recursos que nós temos. Legenda Adriana Zanotto."
+ },
+ {
+ "id_global": 39,
+ "fonte": "1o_debate",
+ "id_local": 39,
+ "timecode": "01:24:37",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "Speaker 1Além disso, há alguma previsão para novos concursos para técnicos, tendo em vista as vacâncias e a falta de reposição de servidores? Chapa 3, com a palavra."
+ },
+ {
+ "id_global": 40,
+ "fonte": "1o_debate",
+ "id_local": 40,
+ "timecode": "01:24:51",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesBom, ficamos muito à vontade para responder a essa pergunta e eu agradeço, porque... Nós estamos na contramão do mundo, com o trânsito caótico que nós temos, com a distância da moradia e o trabalho, as pessoas têm ficado pouco tempo com suas famílias. Nós, enquanto reitor, mantivemos as 30 horas até o final do nosso mandato, porque é muito."
+ },
+ {
+ "id_global": 41,
+ "fonte": "1o_debate",
+ "id_local": 41,
+ "timecode": "01:25:30",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallesimportante essa convivência das pessoas com sua família, tem que ter tempo. Nós temos que cobrar produtividade. Nós vamos simplesmente acabar com o ponto biométrico, porque verificamos que várias universidades não utilizam essa metodologia. Nós vamos formar uma comissão para estudar a melhor forma do técnico administrativo."
+ },
+ {
+ "id_global": 42,
+ "fonte": "1o_debate",
+ "id_local": 42,
+ "timecode": "01:26:01",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallessua jornada com tranquilidade. Tem várias formas de se falar. Teletrabalho, banco de horas. Então, tem que conversar com as pessoas. A maior riqueza que nós temos na nossa instituição são as pessoas que trabalham na nossa instituição. Qualquer empresa é assim. Então, temos que valorizar nossos técnicos administrativos, tem que valorizar nossos docentes e, obviamente, também, como é a universidade, os nossos discentes."
+ },
+ {
+ "id_global": 43,
+ "fonte": "1o_debate",
+ "id_local": 43,
+ "timecode": "01:26:32",
+ "topicos": "Eleições/Processo",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEntão, a nossa proposta é exatamente essa. Rever o que está aí. Não é perto de uma eleição que nós estamos prometendo. Nós temos uma coerência ao longo dos anos e de vivência com as pessoas. Essa caminhada, quanto reitor, de ir aos locais, conversar com as pessoas, sentir o que está acontecendo, quais são as necessidades. E, obviamente, que a universidade precisa realmente crescer cada vez mais."
+ },
+ {
+ "id_global": 44,
+ "fonte": "1o_debate",
+ "id_local": 44,
+ "timecode": "01:27:06",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesVerificamos aqui em campus a quantidade de servidores técnico-administrativos bem pequenos, trabalhando na parte administrativa. Nós não podemos, temos funcionários cedidos, mas que não trabalham exatamente na articulação com os departamentos e com a própria unidade como um todo. Então, nós precisamos, sim, de mais técnico-administrativo."
+ },
+ {
+ "id_global": 45,
+ "fonte": "1o_debate",
+ "id_local": 45,
+ "timecode": "01:27:37",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesSe nós fizemos lá atrás vários concursos, nós sabemos o caminho e vamos fazer de novo. Isso vocês podem ter certeza."
+ },
+ {
+ "id_global": 46,
+ "fonte": "1o_debate",
+ "id_local": 46,
+ "timecode": "01:42:17",
+ "topicos": "30h/Teletrabalho|ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesO pai, junto com o Lula, do Reúne, Fernando Haddad. Inclusive, uma pessoa querida e amiga. E vou votar em Lula, obviamente. Eu não vou votar em ninguém que ataca a educação, o meio ambiente, que ataca o sistema social como um todo, né? Então, isso aí não tem nenhuma dúvida. Agora, eu queria lembrar, já que o reitor falou da questão das 30 horas, né?"
+ },
+ {
+ "id_global": 47,
+ "fonte": "1o_debate",
+ "id_local": 47,
+ "timecode": "01:42:48",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesEu iria ao Supremo, reitor. Se eu fosse reitor, eu iria ao Supremo para defender a posição do nosso... Não, eu vou votar em Lula. Os nossos técnicos administrativos. Eu ia até a última instância. Vou passar aqui a palavra para a Isabel."
+ },
+ {
+ "id_global": 48,
+ "fonte": "1o_debate",
+ "id_local": 48,
+ "timecode": "01:46:37",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Antônio ClaudioOk, nós queremos fazer a pergunta para a chapa 3, por favor. Queremos perguntar o que a chapa entende por sustentabilidade, qual o conceito de sustentabilidade para a chapa e quais são ações concretas nesse sentido. Por favor."
+ },
+ {
+ "id_global": 49,
+ "fonte": "1o_debate",
+ "id_local": 49,
+ "timecode": "01:47:13",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesA sustentabilidade realmente é um termo amplo e gostaria de pedir a todos que acessassem o nosso programa para ver detalhadamente que foi escrito não só por docentes, como técnicos administrativos e também estudantes. É muito importante, nós temos, e foi escrito inclusive por um grande pesquisador da Universidade Federal do Fluminense, um dos maiores."
+ },
+ {
+ "id_global": 50,
+ "fonte": "1o_debate",
+ "id_local": 50,
+ "timecode": "01:47:45",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesNossa universidade, nós temos um problema hoje, por exemplo, energético. O custo da energia é muito elevado. A universidade realmente paga uma conta muito alta. E, obviamente, nós precisamos... Precisamos diminuir essa conta e usar a energia limpa. E nós temos todos aqueles telhados de todos os lugares, seja aqui, seja lá em Pádua, seja em Volta Redonda, nos campos lá de Niterói, um espaço imenso para justamente nós obtermos."
+ },
+ {
+ "id_global": 51,
+ "fonte": "1o_debate",
+ "id_local": 51,
+ "timecode": "01:48:21",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesenergia limpa, através de placas, por exemplo. E temos pesquisadores que estudam isso. Também o recolhimento do material químico dentro da universidade, recolhimento do lixo, recolhimento também do material que é usado na cozinha, como nós fazíamos antes. Então, realmente, a universidade tem essa responsabilidade de tratar de todas essas questões relativas ao meio ambiente, relativo à economia, porque não deixa de ser uma."
+ },
+ {
+ "id_global": 52,
+ "fonte": "1o_debate",
+ "id_local": 52,
+ "timecode": "01:48:55",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto Sallescoisa, economia que é. Então, eu acho que a... O tema, justamente por ser muito amplo, e nós temos várias visões a respeito disso, que nós fizemos um programa especial relativo a essa área. Então, nossa chapa 3 tem uma responsabilidade muito grande em relação à nossa visão de futuro,"
+ },
+ {
+ "id_global": 53,
+ "fonte": "1o_debate",
+ "id_local": 53,
+ "timecode": "01:49:26",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesem relação à economia da universidade, em relação ao meio ambiente, em relação a usar, mecanismos novos de sustentabilidade. Então, gostaria de convidar a todos que não deixassem de visualizar no nosso programa o que nós entendemos por sustentabilidade, dessa forma bem ampla e que acho que atende à demanda, de um modo geral,"
+ },
+ {
+ "id_global": 54,
+ "fonte": "1o_debate",
+ "id_local": 54,
+ "timecode": "01:49:59",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesdos estudantes. Mas não é pronto ainda. Nós precisamos de pessoas que dêem a contribuição. Então, é isso que eu gostaria de falar."
+ },
+ {
+ "id_global": 55,
+ "fonte": "1o_debate",
+ "id_local": 55,
+ "timecode": "01:52:12",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesQuero lembrar que a empresa Enel, antes, Ampla, já trabalhava com projetos dentro da universidade. Dentro dessas agências, existe um fundo, justamente para isso que a universidade já utilizava. Eu estou vendo aqui o superintendente, ele cansou de trabalhar, por exemplo, uma coisa muito simples, a troca de tipo de lâmpadas, para poder economizar. Isso também faz muito bem. A questão do óleo, da cozinha, dos restaurantes."
+ },
+ {
+ "id_global": 56,
+ "fonte": "1o_debate",
+ "id_local": 56,
+ "timecode": "01:52:43",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallesserem reaproveitados. Também é um exemplo muito importante. E a professora Isabel agora vai complementar."
+ },
+ {
+ "id_global": 57,
+ "fonte": "1o_debate",
+ "id_local": 57,
+ "timecode": "01:53:26",
+ "topicos": "Acessibilidade",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesGostaria de fazer para a Chapa 1 saber, nesses anos de reitoria, qual foi o projeto e realmente a ação em relação à acessibilidade na Universidade Federal Fluminense."
+ },
+ {
+ "id_global": 58,
+ "fonte": "1o_debate",
+ "id_local": 58,
+ "timecode": "01:57:03",
+ "topicos": "30h/Teletrabalho|Acessibilidade|ReUni/Infra",
+ "classe": "incomodado",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesA acessibilidade e a inclusão também foi um ponto muito importante dentro do programa de reestruturação e expansão, porque até criamos o setor de acessibilidade e inclusão que a universidade não tinha. Então, isso mostra a importância que damos para o assunto. E também nessa visão que você falou, ampla. Começamos com, inicialmente, ainda não tinha expansão para os municípios, nós fizemos."
+ },
+ {
+ "id_global": 59,
+ "fonte": "1o_debate",
+ "id_local": 59,
+ "timecode": "01:57:34",
+ "topicos": "ReUni/Infra",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesuma parceria com a prefeitura e conseguimos fazer toda aquela urbanização dos campos do Grau Atá, porque antes as pessoas andavam no Paralelepípedo, então não tinham condições de acessar os prédios. Tivemos essa visão de fazer essa urbanização e fomos adaptando os prédios. antigos, até porque era lei, para poder."
+ },
+ {
+ "id_global": 60,
+ "fonte": "1o_debate",
+ "id_local": 60,
+ "timecode": "01:58:04",
+ "topicos": "Acessibilidade|Mobilidade/BuzUFF",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesdar acessibilidade. Agora, temos também a outra questão. O próprio BuzUFF, que foi comprado lá atrás, bem antes da lei, não tem essa acessibilidade. O cadeirante não pode entrar, ou quem tem alguma dificuldade de locomoção, por exemplo, não pode entrar no BuzUFF. Então, esses ônibus têm que ser substituídos. Até porque eles já têm um prazo de validade muito grande. E as máquinas, começam a ter problemas."
+ },
+ {
+ "id_global": 61,
+ "fonte": "1o_debate",
+ "id_local": 61,
+ "timecode": "01:58:35",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEntão, acho que essa visão também é importante. Agora, tem que começar a fazer. Não adianta ficar falando, vou fazer, vou fazer e não faz. Tem um grande plano. Nós iniciamos. E cada reitor tem que botar seu tijolo, continuar. E é isso que nós queremos. Quanto melhor, melhor para a Universidade Federal Fluminense e para as pessoas que têm essas necessidades."
+ },
+ {
+ "id_global": 62,
+ "fonte": "1o_debate",
+ "id_local": 62,
+ "timecode": "02:10:46",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesÉ verdade, o professor Antônio Cláudio foi meu pró-reitor de pesquisa, pós-graduação e obviamente que eu escolhi. Porque nós tínhamos que dar uma oportunidade a ele, que era professor do biomédico, da mesma unidade minha, e ele fez um bom trabalho como pró-reitor de pesquisa e pós-graduação."
+ },
+ {
+ "id_global": 63,
+ "fonte": "1o_debate",
+ "id_local": 63,
+ "timecode": "02:11:17",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEle sempre trabalhou com pesquisa, o feeling dele. Então, nos ajudou bastante, ajudou a Universidade Federal Fluminense. E o professor Fato também. Isso aí não pode ser negado. Agora, isso é uma coisa. A outra coisa é ser gestor da Universidade Federal Fluminense. Ali eu escolhi ele como pesquisador para uma área específica, sobre o nosso comando,"
+ },
+ {
+ "id_global": 64,
+ "fonte": "1o_debate",
+ "id_local": 64,
+ "timecode": "02:11:47",
+ "topicos": "ReUni/Infra",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallessobre a política que nós planejamos para a Universidade durante o projeto de expansão e reestruturação. Tanto é... Que a todo passo, ele se reportava, nós conversávamos e decidimos junto com a equipe. Então, a explicação é essa agora. Como pró-reitor foi isso. Agora, como reitor, aí você tem que dirigir a pergunta para ele. A responsabilidade é dele como reitor."
+ },
+ {
+ "id_global": 65,
+ "fonte": "1o_debate",
+ "id_local": 65,
+ "timecode": "02:12:21",
+ "topicos": "Eleições/Processo",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesAté porque a eleição para reitor é uma eleição para gestor. A universidade tem ensino de graduação, ensino de pós-graduação, pesquisa, inovação e também administração. Então, nós estamos falando de uma eleição para gestor. Agora, como pró-reitor, substituindo o professor Huberto, ele deu continuidade a um projeto existente na universidade."
+ },
+ {
+ "id_global": 66,
+ "fonte": "1o_debate",
+ "id_local": 66,
+ "timecode": "02:12:57",
+ "topicos": "ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesE correspondeu... De acordo com as perspectivas e o planejamento que nós fizemos durante o projeto de expansão e reestruturação, que foi o maior projeto que teve no país, de 280 milhões de reais. Então, não foi uma coisa simples. Ah, mas tinha muito dinheiro. Mas você tem que saber para onde vai chegar o barco. Não é assim, porque tem dinheiro."
+ },
+ {
+ "id_global": 67,
+ "fonte": "1o_debate",
+ "id_local": 67,
+ "timecode": "02:13:29",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesTodas as universidades tiveram dinheiro, muitos recursos, mas não fizeram a metade que a Universidade Federal Fluminense fez. Agradeça a Fernanda Haddad, José Henrique Paim e Luiz Inácio Lula da Silva."
+ },
+ {
+ "id_global": 68,
+ "fonte": "1o_debate",
+ "id_local": 68,
+ "timecode": "02:16:00",
+ "topicos": "Eleições/Processo",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesComo o professor Vladimir falou, nós estamos numa democracia. Então, cada um que quiser ser candidato, que seja, apresenta suas propostas. Agora, o que está acontecendo também, não exime de nós ficarmos de olho no processo de escolha de reitor. Não pode se repetir muitas coisas que aconteceram na eleição passada."
+ },
+ {
+ "id_global": 69,
+ "fonte": "1o_debate",
+ "id_local": 69,
+ "timecode": "02:16:32",
+ "topicos": "Eleições/Processo",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEspero que não aconteça, como abuso do poder econômico, pessoas que não estavam na listagem de votar, votaram. Por exemplo, até agora, não tivemos acesso aos e-mails para poder mandar a mala direta para os três segmentos. E também temos que ter a lista de votação com antecedência, para saber quem está ali, quem está apto a votar ou não. Então, o fato... De estar no momento em que cada um se candidata, não estamos passando carta branca para ninguém."
+ },
+ {
+ "id_global": 70,
+ "fonte": "1o_debate",
+ "id_local": 70,
+ "timecode": "02:17:06",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallesdentro do processo de liso."
+ },
+ {
+ "id_global": 71,
+ "fonte": "1o_debate",
+ "id_local": 71,
+ "timecode": "02:39:13",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEu queria agradecer ao mediador, representando aqui a comissão eleitoral, aos candidatos, presidente da mesa, minha vice, professor Isabel, a todos vocês da plateia, a acolhida aqui da Ana do Francisco. Muito obrigado a todos aqui, a todos que estão nos assistindo. Em, primeiro lugar, eu tenho uma alegria enorme quando eu venho a campo, até porque não."
+ },
+ {
+ "id_global": 72,
+ "fonte": "1o_debate",
+ "id_local": 72,
+ "timecode": "02:39:48",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesvim aqui só para o debate, eu vim aqui muitas vezes porque eu tenho familiares aqui. Durante a minha jornada de reitor, eu tive muitas vezes aqui comigo. Eu estou aqui com a minha equipe, conversando com todos e realmente eu fico muito feliz quando eu retorno e converso com cada um. Os novos eu me apresento, tanto professor, alunos e estudantes. Nós temos o dever e a obrigação, enquanto candidatos, de darmos continuidade ao que nós iniciamos,"
+ },
+ {
+ "id_global": 73,
+ "fonte": "1o_debate",
+ "id_local": 73,
+ "timecode": "02:40:26",
+ "topicos": "30h/Teletrabalho|ReUni/Infra",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesque foi o projeto de expansão desta unidade da UFF em Campos dos Goitacazes. O compromisso está assumido, nós voltaremos aqui como reitor para cumprir o que nós prometemos a todos aqui. Eu queria só dizer, com esclarecimento, que teletrabalho não é paternidade de ninguém, isso é um decreto."
+ },
+ {
+ "id_global": 74,
+ "fonte": "1o_debate",
+ "id_local": 74,
+ "timecode": "02:41:00",
+ "topicos": "Acessibilidade",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesO Ministério da Economia, até quando vem o decreto do Ministério da Economia, nós devemos realmente desconfiar. E uma das provas, quer dizer, tem muitas provas sobre o REUNE de inclusão, mas nós fizemos, construímos com a biologia e outros cursos, o mestrado de inclusão e acessibilidade. Não, inclusão e diversidade. Esse mestrado é extremamente produtivo e é um exemplo da UFF para outras universidades."
+ },
+ {
+ "id_global": 75,
+ "fonte": "1o_debate",
+ "id_local": 75,
+ "timecode": "02:41:36",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEntão foram várias coisas construídas, até o brasão da universidade tivemos um cuidado, não foi só construções enormes, avanços, mas também detalhes. O brasão da UFF foi uma realização nossa, assim como o UFF e outras coisas. Agora. Agora passa a palavra a professora Isabel."
+ },
+ {
+ "id_global": 76,
+ "fonte": "2o_debate",
+ "id_local": 1,
+ "timecode": "00:09:32",
+ "topicos": "Hospital/EBSERH|ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesComo reitor, junto com o Reúne, fizemos o projeto mais ousado do país em termos de investimento. Foram muitos prédios construídos, 25, 140 reformas. Conseguimos reformar o Hospital Antônio Pedro todo. Começou com o Reúne e depois passou para o Reúne. O hospital antes, quando você olhava de fora, parecia que tinha sofrido bombardeio aéreo. Estava caindo aos pedaços. Começamos pelo DIP, a pedido da Ana Bazan, saudosa."
+ },
+ {
+ "id_global": 77,
+ "fonte": "2o_debate",
+ "id_local": 2,
+ "timecode": "00:10:08",
+ "topicos": "Hospital/EBSERH",
+ "classe": "incomodado",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesFizemos esse hospital, um hospital todo equipado e reformado. Saímos em 2014. Em 2016, abril, é só colocar no Google, vocês vão ver, colocaram a Ibser dentro do nosso hospital. E quero dizer que os funcionários concursados não têm nada a ver com isso. O problema é de gestão da cúpula. O que aconteceu nesses oito anos? De lá para cá, de 2016 para cá. O hospital só vem caindo."
+ },
+ {
+ "id_global": 78,
+ "fonte": "2o_debate",
+ "id_local": 3,
+ "timecode": "00:10:38",
+ "topicos": "Hospital/EBSERH",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesDiminuíram o número de leitos. As pessoas pressionadas. O ensino prejudicado está aqui escrito. Preservar o espaço necessário para o processo de ensino e aprendizado destinado à formação profissional, desenvolvimento e pesquisa. Os professores não podem ensinar. A saúde coletiva é muito importante na medicina. E agora nós estamos nessa situação. Vamos fechar o hospital? Vamos desonrar as pessoas que no incêndio do circo vieram para cá, para esse espaço? Os alunos, os professores. Nós temos que refletir sobre isso."
+ },
+ {
+ "id_global": 79,
+ "fonte": "2o_debate",
+ "id_local": 4,
+ "timecode": "00:26:27",
+ "topicos": "Hospital/EBSERH",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEu estou lendo aqui a cláusula sétima desse contrato enorme aqui da EBSERH, assinado em 2016, que diz, no inciso nono, incentivar a produção de conhecimento científico e tecnológico no âmbito do hospital por meio de promoção de projetos de pesquisa e definição de diretrizes. Eu creio que realmente, se não, se estamos diminuindo leitos."
+ },
+ {
+ "id_global": 80,
+ "fonte": "2o_debate",
+ "id_local": 5,
+ "timecode": "00:27:00",
+ "topicos": "Hospital/EBSERH|ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesSe há dificuldade do ensino da graduação, os residentes estão com maior dificuldade. Imagina a produção de conhecimento científico e tecnológico no âmbito do Hospital Universitário Antônio Pedro. Realmente, a UFF agora tem que crescer em qualidade. Nós criamos as bases para o crescimento com o ReUni. Dentro do nosso Hospital Universitário, como eu falei anteriormente, reformamos e equipamos com o que tem de melhor."
+ },
+ {
+ "id_global": 81,
+ "fonte": "2o_debate",
+ "id_local": 6,
+ "timecode": "00:27:35",
+ "topicos": "Hospital/EBSERH",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesRadiologia, então, ressonância magnética, medicina nuclear, tudo do bom e melhor. Para que justamente criasse um ambiente de ensino, pesquisa e extensão e, como consequência, assistência. Isso não foi feito e isso nós temos que recuperar. As pessoas têm que voltar a sorrir dentro do nosso Hospital Universitário. E aí... Os caminhos nós conhecemos, as fontes de financiamento, foi falado aqui em emendas parlamentares,"
+ },
+ {
+ "id_global": 82,
+ "fonte": "2o_debate",
+ "id_local": 7,
+ "timecode": "00:28:07",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesa universidade sempre teve, a faculdade de medicina foi uma negociação dura entre o diretor e o diretório acadêmico, demorou a sair o projeto, mas até 2014 a obra continuou e depois parou por um certo momento."
+ },
+ {
+ "id_global": 83,
+ "fonte": "2o_debate",
+ "id_local": 8,
+ "timecode": "00:30:40",
+ "topicos": "Hospital/EBSERH",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesContinuando a examinar aqui o contrato, na cláusula 7º, inciso 10º, cabe a IBCR destinar recursos para incentivo à pesquisa no hospital universitário, cujo percentual será definido anualmente pela diretoria executiva da conta. Eu pergunto aos senhores, cadê esse recurso para pesquisa dentro do nosso hospital Antônio Pedro? Aqui, o hospital é um ambiente muito importante para pesquisa de várias áreas."
+ },
+ {
+ "id_global": 84,
+ "fonte": "2o_debate",
+ "id_local": 9,
+ "timecode": "00:31:17",
+ "topicos": "Hospital/EBSERH",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEu citei a saúde coletiva, tem enfermagem, tem odontologia, serviço social e as engenharias que podiam estar aqui dentro, descobrindo coisas novas, fazendo inovação. Então, realmente, alguma coisa está errada e nós temos que corrigir. O hospital tem que voltar a sorrir novamente."
+ },
+ {
+ "id_global": 85,
+ "fonte": "2o_debate",
+ "id_local": 10,
+ "timecode": "00:32:22",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesNós vamos perguntar à chapa 2, como que eles visualizam conduzir a avaliação didáticos-científicas dentro da universidade."
+ },
+ {
+ "id_global": 86,
+ "fonte": "2o_debate",
+ "id_local": 11,
+ "timecode": "00:35:59",
+ "topicos": "Transparência/Orçamento",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesO censo universitário é muito importante dentro da universidade, mas temos que ter dados corretos para alimentar esse censo. E foi através dessas avaliações que a UFF em 2013 conseguiu o conceito institucional 5. Poucas universidades conseguiram. Isso reflete na matriz orçamentária. Durante 10 anos, 10 anos a UFF vai ficar com o conceito."
+ },
+ {
+ "id_global": 87,
+ "fonte": "2o_debate",
+ "id_local": 12,
+ "timecode": "00:36:36",
+ "topicos": "Transparência/Orçamento",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallesinstitucional 5 e isso, obviamente, vai repercutir na nossa matriz orçamentária. Mas temos um problema. Tudo fica na mão, tudo fica sob a responsabilidade dos coordenadores de curso, que tem um trabalho tremendo. Os coordenadores, tanto de graduação, pós-graduação, quando recebem... Não recebem verba, não tem uma estrutura para ajudá-los a prestar contas dos recursos."
+ },
+ {
+ "id_global": 88,
+ "fonte": "2o_debate",
+ "id_local": 13,
+ "timecode": "00:37:07",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesque chegam e isso, obviamente, atrapalha o trabalho daquele pesquisador. Então, nós temos que ter, dentro da universidade, um setor responsável por ajudar esses pesquisadores a trabalharem nas suas pesquisas tranquilas, sem se preocupar muito com a burocracia. Isso tem atrapalhado demasiadamente a nossa universidade. Então, os dados que são apresentados têm que ser dados corretos, porque existe um grupo."
+ },
+ {
+ "id_global": 89,
+ "fonte": "2o_debate",
+ "id_local": 14,
+ "timecode": "00:37:45",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesde tempos em tempos que vem avaliar a nossa universidade. Esses dados são colocados no censo, e esses resultados são tornados públicos e, por isso, eles têm que ser publicados. Por isso que a nossa universidade teve um... Um bom desempenho na avaliação institucional em 2013, que vai repercutir por 10 anos. Um minuto para o Treble."
+ },
+ {
+ "id_global": 90,
+ "fonte": "2o_debate",
+ "id_local": 15,
+ "timecode": "00:59:48",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesQuando eu comecei a estudar na UFF, as pessoas falavam... Eu falava assim, você estuda naquela Universidade Federal de Niterói, sempre escutei isso. Depois que nós entramos como reitor, eu falava para as pessoas, não, é a Universidade Federal de Niterói, dos municípios, dos oito municípios do estado do Rio de Janeiro, onde o UFFTA."
+ },
+ {
+ "id_global": 91,
+ "fonte": "2o_debate",
+ "id_local": 16,
+ "timecode": "01:00:23",
+ "topicos": "EAD/Remoto|ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto Sallesinserido, estão no estado todo, no Brasil e no mundo. O projeto Reúne também proporcionou uma grande internacionalização da Universidade. Criamos a superintendência de relações internacionais, criamos o Instituto de Estudos Estratégicos, foi o primeiro no Brasil. Esse acordo que foi falado do BRICS, foi nós que fizemos. Levamos a UFFTA também para a África, através da Universidade Aberta do Brasil, para a Europa."
+ },
+ {
+ "id_global": 92,
+ "fonte": "2o_debate",
+ "id_local": 17,
+ "timecode": "01:01:00",
+ "topicos": "ReUni/Infra",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesFizemos muitas parcerias internacionais para que a UFF fosse inserida no mundo. Então, quando se fala aqui desses acordos bilateral, trilateral, seja o que for, foi tudo construído às bases lá atrás com a criação da Superintendência de Relações Internacionais. Então, a UFF ficou conhecida no mundo inteiro. Então, o Reúne não foi só um projeto de expansão, dobrar o número de alunos,"
+ },
+ {
+ "id_global": 93,
+ "fonte": "2o_debate",
+ "id_local": 18,
+ "timecode": "01:01:35",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallesmultiplicar por quatro a pós-graduação e a pesquisa. Foi também levar o nome da universidade internacionalmente. Isso é importante no ranqueamento da universidade. O conhecimento que as pessoas têm, as citações, isso foi fundamental criar essas bases."
+ },
+ {
+ "id_global": 94,
+ "fonte": "2o_debate",
+ "id_local": 19,
+ "timecode": "01:03:51",
+ "topicos": "EAD/Remoto|ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "Speaker 5Bom, queria perguntar para a chapa 3, o que ele entende com políticas de educação à distância? A distinção entre política de ensino e educação à distância com o ensino remoto e a diferença também, se ele entende, em relação à proposta do governo, do Reúne."
+ },
+ {
+ "id_global": 95,
+ "fonte": "2o_debate",
+ "id_local": 20,
+ "timecode": "01:04:24",
+ "topicos": "EAD/Remoto|ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesComo eu havia falado anteriormente, nós incentivamos, além do ensino presencial, nós demos todo o apoio para a expansão da UFF através da Universidade Aberta do Brasil. Tanto é verdade que pouca gente sabe, a UFF está inserida em seis estados, através da Universidade Aberta do Brasil, que proporcionou capacitação na formação de professores por esse Brasil afora."
+ },
+ {
+ "id_global": 96,
+ "fonte": "2o_debate",
+ "id_local": 21,
+ "timecode": "01:05:00",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesAlém do mais, nós sempre tivemos uma parceria com o governo do Estado, através do SEDERG, e fizemos presente em cursos em vários municípios e também trabalhando na formação de professores, que é fundamental para esse país, porque, por incrível que pareça, ainda temos professores que não têm uma formação adequada. A pandemia transformou realmente todo o país, transformou o ensino, tivemos que nos adaptar."
+ },
+ {
+ "id_global": 97,
+ "fonte": "2o_debate",
+ "id_local": 22,
+ "timecode": "01:05:40",
+ "topicos": "EAD/Remoto",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesAs pessoas falavam ensino à distância, ensino à distância tem toda uma tecnologia, tem que ter equipamentos para poder ensinar, e as pessoas podem ficar vendo os vídeos. O ensino remoto é muito diferente, o ensino remoto, a pessoa está ali, ao vivo, falando. Foi o que a universidade fez. A universidade, as universidades de modo geral, já que não havia como os alunos estarem presentes, então colocou em funcionamento, algumas com a melhor qualidade, outras não, o ensino remoto."
+ },
+ {
+ "id_global": 98,
+ "fonte": "2o_debate",
+ "id_local": 23,
+ "timecode": "01:06:20",
+ "topicos": "Acessibilidade|EAD/Remoto",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesAgora, o grande problema, falar de inclusão digital. Muitos alunos não puderam participar e, como consequência, a evasão vai melhorar, porque não tiveram acesso à internet, não tiveram acesso aos equipamentos. Hoje, no dia de hoje, nós estamos tendo essa dificuldade. O aluno está presente numa aula ao vivo e a cores e, logo depois, ele tem o ensino remoto e não tem acesso."
+ },
+ {
+ "id_global": 99,
+ "fonte": "2o_debate",
+ "id_local": 24,
+ "timecode": "01:06:53",
+ "topicos": "Acessibilidade|EAD/Remoto|ReUni/Infra",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEle não tem acesso à internet. Ele acaba gastando o pouco de crédito que ele tem. ... para acessar o Wi-Fi. Ontem nós tivemos dificuldade no Graguatá, com o nosso celular, olha só, com o nosso celular, de fazer uma reunião, porque não tínhamos ligação, dificuldade. Imagine o aluno. Então, nós temos que promover a inclusão digital na Universidade Federal Fluminense."
+ },
+ {
+ "id_global": 100,
+ "fonte": "2o_debate",
+ "id_local": 25,
+ "timecode": "01:09:40",
+ "topicos": "ReUni/Infra",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesque nós estamos em universidades diferentes. Eu sou membro permanente do Conselho Universitário. Não falta nenhuma reunião. Participo de tudo o que acontece na universidade. Por favor, respeito ao tempo do candidato. Durante as nossas aulas para o curso de farmácia e odontologia, nós vimos que muitos alunos não estavam presentes no momento das aulas."
+ },
+ {
+ "id_global": 101,
+ "fonte": "2o_debate",
+ "id_local": 26,
+ "timecode": "01:10:19",
+ "topicos": "Acessibilidade",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesE alguns alunos depois falavam no particular da dificuldade que eles tiveram para poder acessar. Então, essa que é a grande realidade. Eu estou na universidade desde 1977. Cheguei ao topo da carreira, não foi por acaso. Muito trabalho. Eu sou muito grato à universidade. Então, a realidade da gestão atual, em termos de acessibilidade, é completamente diferente da realidade."
+ },
+ {
+ "id_global": 102,
+ "fonte": "2o_debate",
+ "id_local": 27,
+ "timecode": "01:21:50",
+ "topicos": "Hospital/EBSERH",
+ "classe": "incomodado",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesBom, não existe EBSERH se não houver aprovação pelo Conselho Universitário e assinatura do contrato. Foi feito tudo em 2016, e lá na imprensa com tropa de choque, inclusive tropa de choque municipal, isso tem que ser lembrado, com o reitor e o vice-presente. Em 2016, o reitor assinou o contrato da Ibser. Agora, o que eu fico realmente admirado, que em uma das cláusulas diz."
+ },
+ {
+ "id_global": 103,
+ "fonte": "2o_debate",
+ "id_local": 28,
+ "timecode": "01:22:23",
+ "topicos": "Hospital/EBSERH",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallesque tinha que contratar mão de obra e abrir leitos, depois de um ano. Cinco anos depois, aonde está o fiscal do contrato que não viu que não estava sendo cumprido? Eu, como membro permanente do Conselho, e por adorar a universidade, eu sou muito grato à universidade, convivi a maior parte dos anos na universidade, eu vi que não estava sendo cumprido. E propus uma comissão, junto com a enfermeira Marcia e o técnico administrativo."
+ },
+ {
+ "id_global": 104,
+ "fonte": "2o_debate",
+ "id_local": 29,
+ "timecode": "01:23:00",
+ "topicos": "Hospital/EBSERH",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesQue fizesse uma comissão, foi aprovado pelo Conselho, presidida pelo professor Adalto, com a presença também do componente da enfermeira Márcia, o diretor da enfermagem, professor Enéas, e o diretor da odontologia. Estamos aguardando, foi no final do ano passado, até hoje, o resultado dessa comissão, para analisar o que a comissão vai fazer e com responsabilidade, volto a dizer, que os funcionários concursados da EBSERH não tem nada a ver com isso."
+ },
+ {
+ "id_global": 105,
+ "fonte": "2o_debate",
+ "id_local": 30,
+ "timecode": "01:23:35",
+ "topicos": "30h/Teletrabalho|Hospital/EBSERH",
+ "classe": "incomodado",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesAgora, não dá, não dá para aceitar que a cúpula da EBSERH na universidade não tomou as providências no tempo correto, para não chegar a esse ponto de termos 125. E prejudicar o ensino dos estudantes que estão aqui dentro. Esse que é o fato importante a ser esclarecido. Com responsabilidade. Foi falado aqui que é verdade. A EBSERH, você tem uma cláusula que você tem que denunciar um ano antes."
+ },
+ {
+ "id_global": 106,
+ "fonte": "2o_debate",
+ "id_local": 31,
+ "timecode": "01:24:08",
+ "topicos": "Hospital/EBSERH",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesE durante esse ano tem que saber o que nós vamos fazer para não prejudicar mais nosso hospital. O que nós não podemos aceitar é deixar o tempo passar e o hospital fechar. Quem preside a EBSERH é um general em Brasília. E a EBSERH aqui é diferente de outras universidades. Eu encontrei com funcionários que foram de outros residentes e funciona de outra maneira. Então a questão aqui também é uma questão de gerência."
+ },
+ {
+ "id_global": 107,
+ "fonte": "2o_debate",
+ "id_local": 32,
+ "timecode": "01:24:39",
+ "topicos": "Hospital/EBSERH",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesAgora, se a EBSERH não cumpriu os acordos, nós temos que tomar uma providência e pedir para se retirar. Não dá é para ficar jogando com a barriga. Temos que dar uma decisão. Obrigado, Alexandre."
+ },
+ {
+ "id_global": 108,
+ "fonte": "2o_debate",
+ "id_local": 33,
+ "timecode": "01:29:00",
+ "topicos": "Hospital/EBSERH",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "Speaker 1Agora, responde a chapa 3 em 3 minutos. Repita a pergunta, professor. É necessário repetir a pergunta ou não? Por favor. Qual a proposta para otimizar o uso dos leitos do hospital, contando com as inovações na gestão do cuidado, tipo os cuidados intermediários e paliativos? 3 minutos para a resposta."
+ },
+ {
+ "id_global": 109,
+ "fonte": "2o_debate",
+ "id_local": 34,
+ "timecode": "01:29:26",
+ "topicos": "Hospital/EBSERH",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesBom, primeira questão é saber a relação do nosso hospital, do nosso órgão máximo da universidade, em relação à prefeitura de Niterói. Não podemos permitir que o nosso hospital seja um hospital que a prefeitura dá todo o comando."
+ },
+ {
+ "id_global": 110,
+ "fonte": "2o_debate",
+ "id_local": 35,
+ "timecode": "01:29:56",
+ "topicos": "30h/Teletrabalho|Hospital/EBSERH",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesIsso aqui é um hospital de ensino. A segunda questão, o segundo ponto é que nossos pacientes aqui são, na grande maioria, pacientes oncológicos. O município deveria ter um hospital de apoio para atender esses pacientes sem recuperação terapêutica. E não temos esse hospital de apoio. Se for visitar a emergência, está cheio de pacientes oncológicos."
+ },
+ {
+ "id_global": 111,
+ "fonte": "2o_debate",
+ "id_local": 36,
+ "timecode": "01:30:30",
+ "topicos": "30h/Teletrabalho|Hospital/EBSERH",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesIsso prejudica o ensino, prejudica enormemente. Então, essa relação tem que ser revista também. Não é só a questão da EBSERH. A prefeitura dá o comando ao ponto que se um profissional daqui de dentro passar mal ali atravessando a rua, ele vai ter que ser levado ou para o AZV do Lima ou para o CPN, por incrível que pareça. Então, não dá para aceitar. Que essa relação perdure dessa forma."
+ },
+ {
+ "id_global": 112,
+ "fonte": "2o_debate",
+ "id_local": 37,
+ "timecode": "01:31:05",
+ "topicos": "Geral",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesNós temos que ouvir também a Faculdade de Medicina, o Instituto de Saúde Coletiva, para ver a melhor forma de a gente fazer um rearranjo na condução dos pacientes que entram no Antônio Pedro. Eu pergunto, esses segmentos são ouvidos? A cúpula da EBC convida esses profissionais para conversar, para ver a melhor forma de tratar os pacientes?"
+ },
+ {
+ "id_global": 113,
+ "fonte": "2o_debate",
+ "id_local": 38,
+ "timecode": "01:31:41",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesEscuta os profissionais que trabalham aqui dentro. Isso tudo tem que ser indagado. Afinal de contas, desde 2016 para cá, que nós devíamos ter alguém no... Como fiscal do contrato, ver o que está acontecendo e tomar as providências e ir lá falar com o general que manda nessa empresa privada de direito público ligada ao Ministério da Educação."
+ },
+ {
+ "id_global": 114,
+ "fonte": "2o_debate",
+ "id_local": 39,
+ "timecode": "01:32:16",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEntão, tem situações que tem que ser acusada logo que acontece. Não esperar cinco anos para tomar uma providência e para ter uma comissão para analisar o contrato. Muito obrigado, candidato."
+ },
+ {
+ "id_global": 115,
+ "fonte": "2o_debate",
+ "id_local": 40,
+ "timecode": "01:37:16",
+ "topicos": "Hospital/EBSERH",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesBom, porque eu não sei, mas quem tem que responder são as pessoas que estão há oito anos na universidade administrando e a partir da implantação da IBCER em 2016 pode responder junto com a cúpula da IBCER. Mas eu gostaria de falar que quando nós assumimos a reitoria e quando eu chegava ali na rua da Conceição e olhava para o hospital, o estado que estava."
+ },
+ {
+ "id_global": 116,
+ "fonte": "2o_debate",
+ "id_local": 41,
+ "timecode": "01:37:47",
+ "topicos": "Hospital/EBSERH",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Salleso hospital, eu falei nós temos que tomar uma providência em relação ao hospital e o apelo da professora Ana Bazan, do DIP, foi, determinante para que a gente iniciasse. E naquela oportunidade, eu convidei sim o professor Tarciso para poder nos ajudar na recuperação do hospital, sob o nosso comando. E nós, no final da gestão, depois de oito anos, nós entregamos o hospital todo reformado e equipado."
+ },
+ {
+ "id_global": 117,
+ "fonte": "2o_debate",
+ "id_local": 42,
+ "timecode": "01:38:24",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesMas se tivesse mais um mandato, ele não continuaria. Ele fez um trabalho até aquele ponto. Agora, por que ele continuou mais dois mandatos? Não sei, inclusive agora, como superintendente, não me cabe responder. Mas eu acho, eu acho, na minha opinião, que todo contrato, e eu não sei o nome, não está o nome aqui, tem aqui o contrato, tem o fiscal. O fiscal tem que responder também. Por que que logo no segundo ano..."
+ },
+ {
+ "id_global": 118,
+ "fonte": "2o_debate",
+ "id_local": 43,
+ "timecode": "01:39:00",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesEle viu que não estava sendo cumprido o contrato e tinha que ter alertado a cúpula da universidade, alertado primeiro a cúpula que está na Ibser, pequeno número de pessoas em relação aos concursados, que ganham uma gratificação muito boa para ficarem no comando. Aliás, a Ibser foi muito boa para isso, para pegar umas 15 ou 20 pessoas que são cedidas à Ibser,"
+ },
+ {
+ "id_global": 119,
+ "fonte": "2o_debate",
+ "id_local": 44,
+ "timecode": "01:39:32",
+ "topicos": "30h/Teletrabalho|Transparência/Orçamento",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallespara além do salário da universidade, ganhar um salário. E pior, quando é cedido, a própria empresa Ibser tem que retornar o salário da pessoa à universidade, ainda paga a gratificação, vê a despesa que essa empresa tem dado, de um modo geral, ao orçamento do MEC. Então, acho que quem melhor pode responder essa pergunta são as pessoas... Que estão na universidade sob comando e não ter chegado ao ponto do conselho formar uma comissão."
+ },
+ {
+ "id_global": 120,
+ "fonte": "2o_debate",
+ "id_local": 45,
+ "timecode": "01:40:08",
+ "topicos": "Hospital/EBSERH",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesE nós estamos esperando o resultado, tem mais de quatro meses. Qual é a conclusão da comissão em relação ao cumprimento do contrato ou não da EBSERH."
+ },
+ {
+ "id_global": 121,
+ "fonte": "2o_debate",
+ "id_local": 46,
+ "timecode": "01:47:45",
+ "topicos": "30h/Teletrabalho|Eleições/Processo|Hospital/EBSERH",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesA pergunta vai ser em cima de um assunto também que interessa a todos, todos da universidade, inclusive aqui do hospital. Vou fazer para a chapa 1. A pergunta é o seguinte, o reitor Antônio Cláudio, na eleição passada, entre o primeiro e o segundo turno, ele botou um documento, publicou que era radicalmente favorável às 30 horas."
+ },
+ {
+ "id_global": 122,
+ "fonte": "2o_debate",
+ "id_local": 47,
+ "timecode": "01:48:16",
+ "topicos": "30h/Teletrabalho|Eleições/Processo",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesApós a eleição, não sei o que aconteceu, ele simplesmente disse que não é nada daquilo, serão 40 horas com ponto digital, que é diferente do ponto eletrônico. A pergunta que eu faço, agora o professor Antônio Cláudio vem com uma instrução normativa de 2022 do GAR, seguindo uma instrução normativa de 2020, dois anos de diferença do Ministério do Planejamento, do Ministério da Economia."
+ },
+ {
+ "id_global": 123,
+ "fonte": "2o_debate",
+ "id_local": 48,
+ "timecode": "01:48:56",
+ "topicos": "30h/Teletrabalho|Eleições/Processo",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesProfessor Antônio Cláudio, eu gostaria que você falasse... Eu gostaria que falasse dessa questão de agora, véspera da eleição, vir com teletrabalho. Gostaria que falasse sobre isso. E nós sabemos que é experimental por seis meses. Chapa número um, três minutos para a resposta."
+ },
+ {
+ "id_global": 124,
+ "fonte": "2o_debate",
+ "id_local": 49,
+ "timecode": "01:52:34",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesAs 30 horas começaram a ser concedidas na gestão do professor Raimundo Romeu, continuou com o reitor Gilberto, Pedro Antunes, Cícero, e nós mantivemos independente de pressões. Então, não precisava publicar absolutamente nada. Agora, o reitor falou, e eu até acredito que tenha havido essas ações. Mas, realmente, eu iria até o Supremo."
+ },
+ {
+ "id_global": 125,
+ "fonte": "2o_debate",
+ "id_local": 50,
+ "timecode": "01:53:05",
+ "topicos": "30h/Teletrabalho|Hospital/EBSERH",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesEle disse que foi até o SDJ e depois não foi aceito, mas tudo bem. Agora, essa instrução normativa de 2022, primeiro que o teletrabalho que está colocado aqui não atinge todos os servidores, só uma pequena parte. Por exemplo, o hospital, o Antônio Pedro, praticamente ninguém. Segunda questão, traz toda a despesa para o servidor."
+ },
+ {
+ "id_global": 126,
+ "fonte": "2o_debate",
+ "id_local": 51,
+ "timecode": "01:53:38",
+ "topicos": "30h/Teletrabalho",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesO servidor vai ter que ter equipamentos, ergométricos, vai ter que ter maquinário para trabalhar em casa. E também perde uma série de vantagens, aderindo a isso, como insalubridade, adicional noturno, serviços extraordinários, serviços de transporte. Então, eu... não sei que vantagem é essa que o servidor vai ter aderindo ao teletrabalho. E outra coisa, é experimental por seis meses. A pergunta que eu faço, se a instrução normativa foi."
+ },
+ {
+ "id_global": 127,
+ "fonte": "2o_debate",
+ "id_local": 52,
+ "timecode": "01:54:14",
+ "topicos": "Eleições/Processo",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallespublicada em 31 de setembro de 2020 pelo Ministério da Economia, por que só agora está sendo aplicado novamente perto da eleição? E por que seguir as determinações do Paulo Guedes, já que a universidade gosta de autonomia pelo artigo 207 da Constituição."
+ },
+ {
+ "id_global": 128,
+ "fonte": "2o_debate",
+ "id_local": 53,
+ "timecode": "02:04:49",
+ "topicos": "Hospital/EBSERH",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesClaro que não consolida, né? Tanto que tem universidades que não aderiram à EBSERH. Mas eu queria voltar a uma... O assunto que foi falado aqui, sobre a decisão da... Silêncio, por favor. Eu queria retornar meu tempo."
+ },
+ {
+ "id_global": 129,
+ "fonte": "2o_debate",
+ "id_local": 54,
+ "timecode": "02:05:23",
+ "topicos": "Hospital/EBSERH",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesNós temos na regulação a bipartide e tripartide, sobre como fazer o encaminhamento. E essa decisão da bipartide se dá entre o poder municipal e o hospital, o representante do hospital. Agora, nós não podemos ter uma subserviência em relação ao município de Niterói. Nós temos que ser tratados como iguais."
+ },
+ {
+ "id_global": 130,
+ "fonte": "2o_debate",
+ "id_local": 55,
+ "timecode": "02:05:53",
+ "topicos": "Hospital/EBSERH",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesInclusive, tem gente hoje na cúpula da EBSERH que sempre trabalhou para o município de Niterói. de Niterói. Então, isso é muito importante. E o que foi falado aqui é uma denúncia grave. Antigamente, nós tínhamos números de atendimento dos nossos servidores, tanto os docentes, técnicos e até alunos nos ambulatórios. Ambulatório, diga-se passagem, que iniciou na minha gestão, depois que eu saí eu pedi dinheiro ao Zé Henrique Paim."
+ },
+ {
+ "id_global": 131,
+ "fonte": "2o_debate",
+ "id_local": 56,
+ "timecode": "02:06:24",
+ "topicos": "Eleições/Processo",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto Sallesem 2016. Não dá por uma cúpula pequena que ganha uma gratificação enorme, decidir pelo conjunto. E vou dizer mais, ao assumir, nós vamos promover o que nós fizemos lá atrás, eleição para enfermagem. Vai ser escolhida através da eleição e o diretor também. Quem indica é o reitor."
+ },
+ {
+ "id_global": 132,
+ "fonte": "2o_debate",
+ "id_local": 57,
+ "timecode": "02:06:55",
+ "topicos": "Hospital/EBSERH",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesIsso nós vamos fazer, fizemos e vamos fazer de novo. Nós temos histórico disso, foram duas eleições para enfermagem aqui dentro. E aí isso tem que ser, a comunidade tem que participar, e com isso, obviamente, o hospital fica mais forte."
+ },
+ {
+ "id_global": 133,
+ "fonte": "2o_debate",
+ "id_local": 58,
+ "timecode": "02:09:34",
+ "topicos": "Hospital/EBSERH",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEstava lembrando, durante os oito anos de reitor, quantas vezes eu estive nesse hospital, conversando com as pessoas, sem nenhum grupo atrás de mim, sozinho. Ouvi os alunos no embate do prédio da Faculdade de Medicina. Os alunos participaram ativamente da negociação, porque cederiam espaço de diretório. Foi uma luta de quase quatro anos. Até que nós falamos que a obra tinha que sair, senão ia ficar para trás."
+ },
+ {
+ "id_global": 134,
+ "fonte": "2o_debate",
+ "id_local": 59,
+ "timecode": "02:10:05",
+ "topicos": "Hospital/EBSERH",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesLembro também da farmácia universitária aqui, que nós colocamos para funcionar, vendendo medicamentos a preço de custo para os pacientes que entravam no hospital e não tinham dinheiro para comprar. Até os nossos servidores também fazem uso, não só dos medicamentos comuns, como manipulados. Tudo isso se perdeu. Por isso que eu falo, o hospital, as pessoas que trabalham aqui, tem que voltar a sorrir. Temos que voltar à simplicidade. O hospital tem que voltar a ser o que era."
+ },
+ {
+ "id_global": 135,
+ "fonte": "2o_debate",
+ "id_local": 60,
+ "timecode": "02:10:36",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesObrigado, candidato. Finalizou a rodada 3."
+ },
+ {
+ "id_global": 136,
+ "fonte": "2o_debate",
+ "id_local": 61,
+ "timecode": "02:11:14",
+ "topicos": "Hospital/EBSERH",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesQual a visão deles em relação ao momento atual do ensino, dos cursos que estão dentro do hospital? Vou citar alguns. Medicina, enfermagem, farmácia, odontologia, serviço social. Qual a visão em relação ao que está acontecendo com o ensino, com a estrutura que nós temos, com a situação que temos? E também, se nós estamos realmente valorizando a pesquisa pós-graduação dentro do nosso hospital."
+ },
+ {
+ "id_global": 137,
+ "fonte": "2o_debate",
+ "id_local": 62,
+ "timecode": "02:19:10",
+ "topicos": "Hospital/EBSERH",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Antônio ClaudioEu queria perguntar aos candidatos, considerando esse cenário de desfinanciamento da saúde no Brasil, desfinanciamento crônico e progressivo da saúde no Brasil, e também para as universidades de modo geral, como que os candidatos enxergam que deve ser o financiamento do hospital e da universidade como um todo? Então, minha pergunta é, como lidar com o estrangulamento do comentário? Quais são as soluções possíveis."
+ },
+ {
+ "id_global": 138,
+ "fonte": "2o_debate",
+ "id_local": 63,
+ "timecode": "02:19:47",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesTrês minutos para a resposta. Muito obrigado pela pergunta. Eu já ouvi falar que na época do reúno tinha muito recurso. Todas as universidades tiveram a mesma oportunidade nossa, mas nenhuma universidade fez a metade do que nós fizemos. Para você comandar o navio, você tem que saber o porto que você vai chegar."
+ },
+ {
+ "id_global": 139,
+ "fonte": "2o_debate",
+ "id_local": 64,
+ "timecode": "02:20:17",
+ "topicos": "ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesNão, não são 25 obras entregues e 5 obras por acabar. Então foram 180 mil metros quadrados entregues. E isso aí é uma coisa que está no relatório de gestão, convido todos, é obrigatório. Relatório UFF 2006 e 2014, é só entrar no Google, está tudo lá. Relatório de gestão UFF 2006 e 2014. Bom, vamos lá. É nessa hora que se vê o gestor."
+ },
+ {
+ "id_global": 140,
+ "fonte": "2o_debate",
+ "id_local": 65,
+ "timecode": "02:20:47",
+ "topicos": "Cultura/Cinema|Eleições/Processo|ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesNós estamos fazendo aqui uma eleição para gestor da universidade. Além do que foi conseguido o ReUni, conseguimos recursos extras para o cinema em Caraí, que está lá. É hoje parado. Compramos estacionamento aqui atrás, na Taíde Parreira, antiga NASA, do INSS. Ninguém nem sabe que tem aquele estacionamento da UFF, que paga um preço de mercado no estacionamento. Temos que ter uma relação de igual para igual com os municípios."
+ },
+ {
+ "id_global": 141,
+ "fonte": "2o_debate",
+ "id_local": 66,
+ "timecode": "02:21:18",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesque a UF levou desenvolvimento social e econômico para esses municípios, fazendo concurso. Então, temos que reivindicar o que cabe à UFF desses municípios e do Estado. Temos também que ter um trânsito na Câmara e no Senado, as emendas. As emendas sempre tiveram, individuais e de bancada. Agora, nós estamos contando também que esse governo não vai continuar."
+ },
+ {
+ "id_global": 142,
+ "fonte": "2o_debate",
+ "id_local": 67,
+ "timecode": "02:21:50",
+ "topicos": "ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesVai vir um governo que nós tivemos lá, um governo realmente que goste da educação. Gosto da saúde, gosto do meio ambiente e gosto da população. Então é isso, temos que fazer parcerias também, como fizemos com várias empresas, Petrobras, inclusive empresas privadas, desde que não interfiram na autonomia. E sempre com o olho na autonomia universitária."
+ },
+ {
+ "id_global": 143,
+ "fonte": "2o_debate",
+ "id_local": 68,
+ "timecode": "02:22:20",
+ "topicos": "Transparência/Orçamento",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesAliás, o grupo de trabalho que eu presidi na Câmara dos Deputados, que tinha um grupo de ex-reitores e consultores parlamentares, fizemos o projeto da autonomia tramitar, do Gastão Vieira, colocamos a extensão como fazendo parte obrigatória da grade, o Rocieli aceitou e vai interferir na matriz. Então, quem já fez, quem sabe os caminhos, obviamente que vai repetir isso, com toda certeza."
+ },
+ {
+ "id_global": 144,
+ "fonte": "2o_debate",
+ "id_local": 69,
+ "timecode": "02:25:02",
+ "topicos": "Cultura/Cinema|Hospital/EBSERH",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesO reitor, precisou frisar que o hospital é 100% SUS, claro, sempre foi e sempre será. Não tem nada a ver com empresa privada. Empresa privada é a relação com a universidade inteira e empresas públicas também, que pode ser feita desde que não interfira com autonomia. Agora, o cinema Icaraí, para esclarecimento, foi comprado e nós fizemos um concurso de ideia com alunos de arquiteturas, que demorou."
+ },
+ {
+ "id_global": 145,
+ "fonte": "2o_debate",
+ "id_local": 70,
+ "timecode": "02:25:34",
+ "topicos": "Eleições/Processo",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesA propriedade para construir, fazer alguma coisa, tem que passar para a UFF, demorou. Fizemos a listação do projeto básico executivo. Se vocês colocarem no Google dezembro de 2016, o que o reitor que me sucedeu disse que seria prioridade. Então, há oito anos não fizeram nada. Alguma coisa tem que ser feita. Então, é isso. Não dá para ficar só cobrando o que deixou o legado. O estacionamento está lá. Vê de quem é a propriedade."
+ },
+ {
+ "id_global": 146,
+ "fonte": "2o_debate",
+ "id_local": 71,
+ "timecode": "02:26:04",
+ "topicos": "Geral",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesSe foi devolvida ao NSS, essa é a pergunta. Eu não sei. Conclua, candidato. Obrigado."
+ },
+ {
+ "id_global": 147,
+ "fonte": "2o_debate",
+ "id_local": 72,
+ "timecode": "02:40:35",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesGostaria de agradecer a atenção de todos, o trabalho também de todos que estão trabalhando aqui, nesse momento importante. E dizer que eu vou colocar de público a ata do Conselho de Curadores de dezembro de 2019. E essa ata não pode mudar. foi aprovada. E aqui, o pró-reitor de planejamento da sua gestão, Antônio Cláudio, ele diz."
+ },
+ {
+ "id_global": 148,
+ "fonte": "2o_debate",
+ "id_local": 73,
+ "timecode": "02:41:09",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallesaqui que nós deixamos 55 milhões de resto a pagar, que foram pagos em 2015 e 2016, depois do investimento de 380 milhões. Na verdade, ficaram, para serem pagos, em relação ao final do ano, 23 milhões. Então, você deve estar se referindo de 80 milhões do reitor que você sucedeu, que você era vice, que ficou quatro anos e não fez absolutamente."
+ },
+ {
+ "id_global": 149,
+ "fonte": "2o_debate",
+ "id_local": 74,
+ "timecode": "02:41:41",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallesnada. Porque aqui, na ata do Conselho de Curadores, está escrito e dito pelo seu pró-reitor, não é por mim, não. Então, nós vamos dar publicidade, porque a verdade também tem que ser restabelecida na universidade. Não se pode jogar só com números, tem que se falar... Na verdade, eu estou com a ata aqui, estou mostrando a ata. E nós vamos dar ciência e queremos saber também quanto foi economizado na pandemia. Dois anos sem gasto nenhum."
+ },
+ {
+ "id_global": 150,
+ "fonte": "2o_debate",
+ "id_local": 75,
+ "timecode": "02:42:14",
+ "topicos": "30h/Teletrabalho|Eleições/Processo|Hospital/EBSERH",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesBandejões, prestadores de serviços demitidos. Então, na verdade, nós estamos em um processo que nós não temos inimigo, nem adversários somos. Nós temos pontos de vista diferentes. Agora, não dá para continuar assim. Agora, outra questão é que eu volto a repetir. No primeiro ato nosso é convidar toda a cúpula, toda a cúpula, não os trabalhadores, toda a cúpula da EBSERH, agradecer para se retirar. E nós vamos fazer eleição para diretor de enfermagem e para o superintendente."
+ },
+ {
+ "id_global": 151,
+ "fonte": "2o_debate",
+ "id_local": 76,
+ "timecode": "02:42:52",
+ "topicos": "Hospital/EBSERH",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesVamos tratar com equilíbrio o que vai em relação ao contrato com a EBSERH. Vamos fazer uma comissão. Tem pessoas... ...competentes aqui dentro do hospital, de todas as áreas que sabem como conduzir isso. Então, você fala em seriedade, universidade, você vai fazer 40, vou fazer 45 anos de UFF, vivi muita coisa dentro da UFF. E quero comunicar, convidar a pessoa que falou ainda agora, assistir lá a minha aula de virologia e de TST e conhecer o que é RAD."
+ },
+ {
+ "id_global": 152,
+ "fonte": "2o_debate",
+ "id_local": 77,
+ "timecode": "02:43:26",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesRealmente, ninguém chega ao topo da carreira que não seja com muito trabalho e dedicação à universidade. Eu sou grato e sou muito dedicado à universidade e vou continuar. Muito obrigado."
+ },
+ {
+ "id_global": 153,
+ "fonte": "3o_debate",
+ "id_local": 1,
+ "timecode": "00:06:26",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesMeu nome é Roberto Salles, sou professor de microbiologia e parasitologia do Instituto Biomédico. Entrei nessa universidade em 1977 como aluno. Convivo com a universidade há 45 anos, contando o tempo de aluno. E vi a universidade crescer ao longo desses anos todos, considerando que a universidade possui 62 anos."
+ },
+ {
+ "id_global": 154,
+ "fonte": "3o_debate",
+ "id_local": 2,
+ "timecode": "00:06:57",
+ "topicos": "ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesAqui eu estou muito à vontade. Para conversar com a comunidade, como a Isabel falou, o projeto Reúne foi um grande projeto de reestruturação e expansão das universidades. Através desse projeto, tivemos a oportunidade de levar a universidade para oito municípios do estado do Rio de Janeiro. Isso foi inverter o caminho. Os alunos tinham que ir para Niterói estudar na UFF, e a UFF foi ao interior, aos municípios, procurar os seus estudantes."
+ },
+ {
+ "id_global": 155,
+ "fonte": "3o_debate",
+ "id_local": 3,
+ "timecode": "00:07:33",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesEntão, isso foi uma coisa muito boa. Aqui, especificamente, nós tínhamos quatro cursos de engenharia. Criamos a engenharia de agronegócio. Fizemos uma obra lá na vila, estou me referindo à vila, uma obra no edifício... Fizemos dois andares... Nós formamos laboratórios de pesquisa e aqui no aterrado nós construímos esse conjunto de blocos de 2009, terminamos em 2012, isso deu uma vida muito grande aterrado, obviamente que sempre procurando respeitar a vontade da comunidade, sempre de baixo para cima, não de cima para baixo."
+ },
+ {
+ "id_global": 156,
+ "fonte": "3o_debate",
+ "id_local": 4,
+ "timecode": "00:23:41",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesNós vamos fazer a pergunta para a chapa 2. Chapa 2. Gostaríamos de saber, na sua visão, como se encontra hoje a organização administrativa, considerando o que... O que foi feito em relação à proposta da instrução normativa baixada pela reitoria sobre a nova forma de trabalho, teletrabalho, seguindo a política do Guedes, que baixou."
+ },
+ {
+ "id_global": 157,
+ "fonte": "3o_debate",
+ "id_local": 5,
+ "timecode": "00:24:19",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesa instrução normativa em 2020."
+ },
+ {
+ "id_global": 158,
+ "fonte": "3o_debate",
+ "id_local": 6,
+ "timecode": "00:27:44",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesO Wilson, eu só acho que qualquer decisão que se tome na universidade, que vá atingir um dos segmentos, eu acho que nós devemos primeiro conversar com o segmento. Com o segmento, para poder ver qual a maneira melhor de se resolver a questão antes de qualquer decisão. O que eu sempre achei e acho que devemos consultar as pessoas interessadas, no caso, estamos referindo aos técnicos administrativos, para saber o que eles acham das medidas que foram tomadas."
+ },
+ {
+ "id_global": 159,
+ "fonte": "3o_debate",
+ "id_local": 7,
+ "timecode": "00:28:30",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesMesmo que tenha sido imposto pelo Ministério Público, e eu, se eu fosse reitor, eu evocava o artigo 207 da Constituição, iria ao Supremo. Mas, se não houvesse solução, teríamos que conversar com o segmento para ver qual a melhor maneira de cumprir o seu trabalho, sem prejudicar ninguém. E eu acho que... O que foi colocado e hoje tem uma nova decisão, prejudica muito os técnicos administrativos."
+ },
+ {
+ "id_global": 160,
+ "fonte": "3o_debate",
+ "id_local": 8,
+ "timecode": "00:29:08",
+ "topicos": "EAD/Remoto",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesporque retira uma série de direitos e também é uma decisão experimental por seis meses. Então, a nossa opinião é que é importante ouvir o segmento que está sendo acionado por uma decisão, ouvi-los e ver a opinião. Então, sempre achei que nós devemos tomar as decisões baseadas no que a comunidade."
+ },
+ {
+ "id_global": 161,
+ "fonte": "3o_debate",
+ "id_local": 9,
+ "timecode": "00:29:40",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallespensa e depois se tira uma decisão sobre o assunto."
+ },
+ {
+ "id_global": 162,
+ "fonte": "3o_debate",
+ "id_local": 10,
+ "timecode": "00:33:21",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesBom, a pandemia, infelizmente, além de ceifar vidas, deixar pessoas doentes, trazer tristezas, e eu quero já lamentar tudo o que aconteceu, até por uma política errada do governo, do meu ponto de vista, ela trouxe uma nova realidade. Nós temos que nos adaptar ao momento, às tecnologias."
+ },
+ {
+ "id_global": 163,
+ "fonte": "3o_debate",
+ "id_local": 11,
+ "timecode": "00:34:00",
+ "topicos": "EAD/Remoto",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesE esse tipo de ensino que estamos acontecendo agora, tivemos inicialmente o ensino remoto, que é diferente de ensino à distância. Ensino à distância requer toda uma tecnologia, material, livros, vídeos. E nós tivemos o ensino remoto, que o professor entra em sala e ministra a aula direto para o aluno. Mas, nesse momento agora, de retorno parcial, nós temos o ensino híbrido."
+ },
+ {
+ "id_global": 164,
+ "fonte": "3o_debate",
+ "id_local": 12,
+ "timecode": "00:34:30",
+ "topicos": "Acessibilidade|EAD/Remoto",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesTanto o ensino remoto quanto o presencial. Mas isso requer também acesso à internet. Aí nós vamos falar da inclusão digital. É necessário. O aluno, às vezes, tem uma aula, logo depois, uma aula remota, e o que ele vai fazer? Vai utilizar o que ele tem, o pouco que ele tem no celular? Isso também nós temos que pensar. Obviamente que esse governo que está instalado no país, Ele pensa em algumas coisas, mas sempre prejudicial à universidade."
+ },
+ {
+ "id_global": 165,
+ "fonte": "3o_debate",
+ "id_local": 13,
+ "timecode": "00:35:05",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesE queremos falar claramente, acho que todo mundo já se posicionou, dessa loucura que é a tentativa de cobrar mensalidades, mais uma vez. Isso aí já é uma coisa antiga, mas que não vai passar de jeito nenhum. Bom, eu queria também falar aqui rapidamente sobre uma proposta do governo para baratear o ensino,"
+ },
+ {
+ "id_global": 166,
+ "fonte": "3o_debate",
+ "id_local": 14,
+ "timecode": "00:35:37",
+ "topicos": "30h/Teletrabalho|EAD/Remoto",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesporque eles não encaram o ensino como um investimento, é colocar, avançar no ensino à distância nas universidades. Isso, no meu ponto de vista, é querer realmente precarizar o nosso ensino. O ensino à distância é importante. Nós temos a Universidade Aberta do Brasil, temos também a CCIE, No estado do Rio de Janeiro, ele é importante, claro, mas não pode ser o principal modo de ensino das universidades federais."
+ },
+ {
+ "id_global": 167,
+ "fonte": "3o_debate",
+ "id_local": 15,
+ "timecode": "00:36:11",
+ "topicos": "Transparência/Orçamento",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesA convivência é importante entre os alunos, com alunos como professores e técnico administrativo. Então, nós queremos, sim, que o governo invista em educação, repare o que ele tirou dos orçamentos e possamos voltar a uma nova realidade."
+ },
+ {
+ "id_global": 168,
+ "fonte": "3o_debate",
+ "id_local": 16,
+ "timecode": "00:38:27",
+ "topicos": "EAD/Remoto",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesQuando o Fernando Haddad era ministro, houve um grande impulsionamento através da Universidade Aberta do Brasil, do ensino à distância, e foi importante porque trabalhou na..."
+ },
+ {
+ "id_global": 169,
+ "fonte": "3o_debate",
+ "id_local": 17,
+ "timecode": "00:39:00",
+ "topicos": "EAD/Remoto",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallesformação de professores. Sabemos que existem muitos professores do ensino básico, do ensino fundamental, que não têm a formação. Então, isso deu um salto muito grande. E também através do CEDERJ, nós levamos a universidade a vários municípios, às vezes distritos, que as pessoas não teriam condições de estudar. Então, realmente, tem um momento,"
+ },
+ {
+ "id_global": 170,
+ "fonte": "3o_debate",
+ "id_local": 18,
+ "timecode": "00:39:30",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallestem um espaço importante. Mas não pode ser o principal quando se pensa em uma universidade, federal, ainda mais uma universidade como a Universidade Federal Fluminense."
+ },
+ {
+ "id_global": 171,
+ "fonte": "3o_debate",
+ "id_local": 19,
+ "timecode": "00:40:26",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesEu acho que esse é um tema muito importante. Gostaria de perguntar à chapa 1, qual é a visão dele sobre autonomia universitária? E quais são os instrumentos necessários para que seja realizado, para que seja realmente, possa se concretizar nas universidades."
+ },
+ {
+ "id_global": 172,
+ "fonte": "3o_debate",
+ "id_local": 20,
+ "timecode": "00:44:14",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesCom esse governo instalado no Brasil, é muito difícil que haja recomposição. Nós estamos já pensando no futuro. Na verdade, tive a oportunidade de participar coordenando um grupo de trabalho sobre educação superior na Câmara dos Deputados. Nesse grupo, nós tínhamos três ex-reitores e mais dois consultores legislativos e descobrimos que tinham quatro projetos de autonomia universitária."
+ },
+ {
+ "id_global": 173,
+ "fonte": "3o_debate",
+ "id_local": 21,
+ "timecode": "00:44:49",
+ "topicos": "Eleições/Processo",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesTodos os quatro foram apensados ao projeto do deputado Gastão Vieira e começou a tramitar. Sem autonomia, como tem as universidades paulistas... Realmente, todas as universidades vão ficar subordinadas às vontades de quem está no poder naquele momento. Mesmo dizendo que nós temos autonomia didática, financeira, acadêmica, de livre expressão, mas toda hora surgem portarias, instruções normativas nos impondo alguma coisa."
+ },
+ {
+ "id_global": 174,
+ "fonte": "3o_debate",
+ "id_local": 22,
+ "timecode": "00:45:25",
+ "topicos": "Eleições/Processo",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEntão, a saída, sim, é a autonomia universitária. Infelizmente, não foi possível ou não quiseram fazer a proposta de autonomia lá atrás, quando tinha um governo favorável, e nós estamos nessa situação. Agora, as paulistas têm autonomia e têm vinculação financeira. É atrelada à arrecadação do ICMS do Estado de São Paulo. Dá uma quantidade de dinheiro enorme e, por isso, tem autonomia de tudo."
+ },
+ {
+ "id_global": 175,
+ "fonte": "3o_debate",
+ "id_local": 23,
+ "timecode": "00:45:58",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesE as universidades... As universidades federais não podem ficar sujeitas a governos que não gostam da educação, não gostam do meio ambiente, não gostam de saúde. Então, vamos brigar, sim, pela autonomia das universidades com vinculação financeira para que ninguém tenha nenhum problema de recursos."
+ },
+ {
+ "id_global": 176,
+ "fonte": "3o_debate",
+ "id_local": 24,
+ "timecode": "00:57:40",
+ "topicos": "Cultura/Cinema",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesBom, na nossa universidade, nós temos departamento de artes e produção cultural. A universidade também tem alguns equipamentos importantes, como o cinema da reitoria, o centro de artes, E nós temos também que incentivar toda e qualquer iniciativa para que as artes possam ser, todas as expressões artísticas possam ser propagadas por todos os locais em que a UFF estiver presente, todos os municípios."
+ },
+ {
+ "id_global": 177,
+ "fonte": "3o_debate",
+ "id_local": 25,
+ "timecode": "00:58:25",
+ "topicos": "30h/Teletrabalho|Cultura/Cinema|ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesTivemos agora em campo, recebemos um documento de uma professora sobre colocar no espaço que está sendo construído os dois blocos de prédios extremamente grandes. Já estava prevendo uma parte para que seja instalado lá um local para essas expressões artísticas e culturais. Eu acho que cabe a administração incentivar toda e qualquer iniciativa nesse ponto."
+ },
+ {
+ "id_global": 178,
+ "fonte": "3o_debate",
+ "id_local": 26,
+ "timecode": "00:59:00",
+ "topicos": "Cultura/Cinema",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesA universidade não é só ensino, pesquisa, extensão e até assistência como consequência do TRIPER, mas também é participar e incentivar desses eventos. Por exemplo, nós temos a Orquestra Sinfônica Nacional. Na nossa gestão, nós não tínhamos quase músicos do quadro. Falei com o Fernando Haddad e ele fez concurso para músicos da orquestra,"
+ },
+ {
+ "id_global": 179,
+ "fonte": "3o_debate",
+ "id_local": 27,
+ "timecode": "00:59:30",
+ "topicos": "Cultura/Cinema",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallescomprou instrumentos. Isso foi importante. Também temos a nossa editora da Universidade Federal Fluminense, que, em convênio com o Banco do Brasil, fizemos um espaço belíssimo. Inclusive, espalhamos uma série de módulos dessa edUFF por várias áreas da universidade. Então, isso tudo faz parte da forma dessa expressão. Artístico e cultural."
+ },
+ {
+ "id_global": 180,
+ "fonte": "3o_debate",
+ "id_local": 28,
+ "timecode": "01:00:01",
+ "topicos": "Cultura/Cinema",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesAgora, nós temos que ouvir as pessoas, que trabalham na área, que fazem parte tanto do Departamento de Arte e Produção Cultural, tem tanto o Niterói quanto o Rio das Ouros, e agora também tem uma professora em campus, reivindicando. Eu acho que isso faz parte do dia a dia da universidade. Aliás, todos esses equipamentos que nós temos lá, não servem só os estudantes, os professores e alunos,"
+ },
+ {
+ "id_global": 181,
+ "fonte": "3o_debate",
+ "id_local": 29,
+ "timecode": "01:00:31",
+ "topicos": "Cultura/Cinema",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallese sim a toda a comunidade de Niterói, São Gonçalo e até gente do Rio de Janeiro. Eu lembro que tivemos incentivos para levar a orquestra para a rua, para tocar em vários locais, até em outros estados e municípios. Então, a universidade é isso. Faz parte da universidade também essa expressão toda, artística e cultural."
+ },
+ {
+ "id_global": 182,
+ "fonte": "3o_debate",
+ "id_local": 30,
+ "timecode": "01:03:11",
+ "topicos": "Cultura/Cinema",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesMais uma vez, eu volto aqui a falar da importância de se ouvir a comunidade. Essas manifestações artísticas e culturais, elas devem ser incentivadas, devem partir da comunidade. Nós temos pessoas que conhecem o assunto. E foi falado aqui da orquestra, se nós não tivéssemos conseguido vagas para concurso na orquestra,"
+ },
+ {
+ "id_global": 183,
+ "fonte": "3o_debate",
+ "id_local": 31,
+ "timecode": "01:03:44",
+ "topicos": "Cultura/Cinema",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallestalvez hoje nós não tivéssemos a orquestra sinfônica. Não foi só o concurso, o instrumento também. Mas eu acho importante ouvir a comunidade antes de apresentar qualquer iniciativa em qualquer área. Isso é fundamental. O que nós temos que fazer é apoiar qualquer iniciativa nesse sentido e, obviamente, também procurar parcerias. Afinal, nós temos aí dez municípios e dez prefeitos."
+ },
+ {
+ "id_global": 184,
+ "fonte": "3o_debate",
+ "id_local": 32,
+ "timecode": "01:20:50",
+ "topicos": "Governança/PDI|Mobilidade/BuzUFF|Transparência/Orçamento",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesBom, foi, como foi falado aqui, o equipamento tem 12 anos, foram comprados ainda dentro da nossa gestão de 2006 a 2014, assim como também... Praticamente todos os BUZUFF que precisam realmente de uma troca. Então, como a professora Isabel falou, é muito importante uma discussão, trazer à tona de novo a discussão sobre o PDI, sobre o Plano de Desenvolvimento Institucional, que funciona como orçamento participativo."
+ },
+ {
+ "id_global": 185,
+ "fonte": "3o_debate",
+ "id_local": 33,
+ "timecode": "01:21:23",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesTodo mundo opina e diz as prioridades. Ainda mais no momento que foi falado que tem pouco recurso com cortes orçamentários, a discussão da comunidade é importante para apontar os caminhos, o que é prioritário na universidade. Mas, de qualquer forma, falando agora também na questão de políticas afirmativas, é muito importante escutar os estudantes sobre o que está acontecendo. Nós fazíamos a reitoria itinerante."
+ },
+ {
+ "id_global": 186,
+ "fonte": "3o_debate",
+ "id_local": 34,
+ "timecode": "01:21:55",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesNós trazíamos de tempo em tempo, em todas as unidades. O grupo de pró-reitores, superintendentes, para discutir, não só com os estudantes, com os professores, com os técnicos administrativos, as questões mais urgentes daquela unidade. Então, nós temos o compromisso de continuar fazendo o que deu certo, a reitoria itinerante."
+ },
+ {
+ "id_global": 187,
+ "fonte": "3o_debate",
+ "id_local": 35,
+ "timecode": "01:34:50",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesNós estamos na contramão do mundo. O Japão já extinguiu um dia sem redução de salário. Na Europa é a mesma coisa. As pessoas, no sistema de transporte que nós temos, perdem muito tempo entre o trabalho e sua casa. Deixam de conviver com suas famílias. Lá atrás, o professor José Raimundo implantou as 30 horas. Foram seguidos pelo professor Edilberto, pelo professor Pedro Antunes, pelo Cícero,"
+ },
+ {
+ "id_global": 188,
+ "fonte": "3o_debate",
+ "id_local": 36,
+ "timecode": "01:35:20",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto Sallese nos dois mandatos nossos. Nós vamos usar a Constituição, o artigo 207. Vamos retornar as 30 horas. Vamos formar uma comissão, mesmo antes da posse, para conversar com os técnicos administrativos. Se for preciso, nós vamos ao Supremo. Vamos ao Supremo para podermos ter o que nós tínhamos antes, que foi cortado nesses oito anos, que é as 30 horas para os nossos servidores."
+ },
+ {
+ "id_global": 189,
+ "fonte": "3o_debate",
+ "id_local": 37,
+ "timecode": "01:35:53",
+ "topicos": "30h/Teletrabalho",
+ "classe": "incomodado",
+ "escore": 4,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesO que interessa é o que Isabel falou, é a produtividade. Não é o tempo que a pessoa fica. Então, e o ponto biomédico também não segura ninguém dentro da universidade, sabemos disso. Agora, vimos sim, conversamos com vários servidores, que em alguns lugares não aplicavam as 30 horas à época da nossa gestão. E nós fomos saber disso há pouco tempo. Então, isso é um absurdo total."
+ },
+ {
+ "id_global": 190,
+ "fonte": "3o_debate",
+ "id_local": 38,
+ "timecode": "01:36:23",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesNós vamos retornar as 30 horas, não tenho dúvida nenhuma disso. E vamos usar a autonomia universitária, e vamos ao Supremo para manter as 30 horas."
+ },
+ {
+ "id_global": 191,
+ "fonte": "3o_debate",
+ "id_local": 39,
+ "timecode": "01:39:03",
+ "topicos": "Geral",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesLucas de Almeida, muito obrigado pela pergunta. Como eu falei inicialmente, um dos mecanismos que nós utilizamos para poder ouvir a comunidade, inclusive os estudantes, era vir com a equipe toda para a volta redonda, tanto na Vila quanto na Terrado, trazendo todos os pró-reitores e superintendentes para poder saber com os estudantes quais são os anseios."
+ },
+ {
+ "id_global": 192,
+ "fonte": "3o_debate",
+ "id_local": 40,
+ "timecode": "01:39:34",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto Sallese o que estava ocorrendo. Isso foi muito importante e não foi feito uma vez, não. Foi feito durante os oito anos da nossa gestão. Sempre presente aqui, se perguntar aos técnicos, aos administrativos mais antigos, aos professores, eles vão confirmar isso. Então, essa é uma maneira importante de fazer esse contato. Agora, o segundo ponto, nós temos uma ouvidoria que nós criamos na nossa gestão, não sei."
+ },
+ {
+ "id_global": 193,
+ "fonte": "3o_debate",
+ "id_local": 41,
+ "timecode": "01:40:07",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallescomo se encontra hoje, que recebia as informações e rapidamente respondia não só aos estudantes, aos professores e aos funcionários. Esse foi um mecanismo importante, mas não era um mecanismo próximo, mas funcionava quando se ligava para lá e se passava e-mail, havia uma resposta rápida. Agora, o que tem que ser feito é estreitar cada vez mais essa distância e a maneira de fazer isso, nós criamos três pró-reitorias, nós tínhamos quatro, e várias superintendências."
+ },
+ {
+ "id_global": 194,
+ "fonte": "3o_debate",
+ "id_local": 42,
+ "timecode": "01:40:41",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesÉ criar uma pró-reitoria de integração, nomeando uma pessoa escolhida pelos municípios aonde a UFF estiver presente e esse superintendente vai atender diretamente. As unidades da UFF nos municípios e trazer as reivindicações o mais rápido possível. Esse também seria um mecanismo importante de aproximação da gestão central com as unidades."
+ },
+ {
+ "id_global": 195,
+ "fonte": "3o_debate",
+ "id_local": 43,
+ "timecode": "01:41:19",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesPorque é muito importante, desde o começo eu estou falando, escutar a comunidade, escutar em tudo, qualquer projeto, antes de decidir qual vai ser o projeto. E isso nós sempre fizemos e vamos fazer, que é continuar essa proximidade, vindo com a pró-reitoria itinerante, conversando com todos. Isso deu em todos os municípios que a UFF estava presente. Isso aí nós não vamos abrir mãos."
+ },
+ {
+ "id_global": 196,
+ "fonte": "3o_debate",
+ "id_local": 44,
+ "timecode": "01:41:49",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesE também criar uma pró-reitoria de integração para poder aproximar todos vocês da decisão do poder central. É isso que nós..."
+ },
+ {
+ "id_global": 197,
+ "fonte": "3o_debate",
+ "id_local": 45,
+ "timecode": "02:05:27",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 6,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesBom, a política para os técnicos administrativos foi uma política que nós sempre fizemos. Primeiro, criar em respeito e a importância dos nossos técnicos administrativos, nós criamos a pró-reitoria de gestão de pessoas. Isso foi muito importante. Segundo lugar, reformamos todo o setor e equipamos. Eu saí em 2014."
+ },
+ {
+ "id_global": 198,
+ "fonte": "3o_debate",
+ "id_local": 46,
+ "timecode": "02:05:58",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesO segundo... O avanço foi dentro da pesquisa pós-graduação, nós incentivarmos os nossos técnicos administrativos a fazerem curso de mestrado e doutorado. Os professores têm os caminhos próprios, os técnicos não tinham. Também curso de especialização. O segundo valorização foi que nós reformamos, à época, todo o serviço médico odontológico."
+ },
+ {
+ "id_global": 199,
+ "fonte": "3o_debate",
+ "id_local": 47,
+ "timecode": "02:06:30",
+ "topicos": "Hospital/EBSERH",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallese fizemos concursos públicos para que nossos servidores, aí incluindo os docentes também e até o aluno, fossem atendidos num ambiente tranquilo, num ambiente saudável. A outra questão também foi que nós abrimos... A farmácia universitária, em que muitas das pessoas iam no hospital, não tinha como comprar o remédio. E acabavam voltando pior ainda. E nossos técnicos, também, assim como os docentes, alunos, também compravam medicamento nessa farmácia. E também, não pensando nos nossos servidores, à época, nós estabelecemos que dentro do Hospital Antônio Pedro, nós teríamos o número de atendimentos para os nossos técnicos administrativos."
+ },
+ {
+ "id_global": 200,
+ "fonte": "3o_debate",
+ "id_local": 48,
+ "timecode": "02:07:27",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesIsso tudo acabou. Na verdade, isso não existe mais, infelizmente. E também abrimos um posto de atendimento de urgência no campus do Graguatá e Valonguinho, para atender os nossos funcionários. E a outra valorização para as unidades nos municípios foi a criação que nós fizemos da reitoria itinerante. E é para todos os setores. Então, nós temos pessoas extremamente competentes, que conhecem a administração pública. Conhecem gestão de pessoas."
+ },
+ {
+ "id_global": 201,
+ "fonte": "3o_debate",
+ "id_local": 49,
+ "timecode": "02:08:00",
+ "topicos": "Eleições/Processo",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesE logo em terminar a eleição, nós venceremos a eleição e nós convidaremos um grupo de pessoas para estudar uma política para os quatro anos seguintes, para os nossos gloriosos servidores. E sempre falei, a maior riqueza que nós temos na nossa universidade são as pessoas que trabalham e estudam na universidade. A maior riqueza de uma empresa são as pessoas que trabalham lá. E nós temos que valorizar, não enganar e maltratar."
+ },
+ {
+ "id_global": 202,
+ "fonte": "3o_debate",
+ "id_local": 50,
+ "timecode": "02:10:45",
+ "topicos": "Hospital/EBSERH",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesNão foi isso que nós observamos dentro da universidade nos últimos oito anos. Não foi isso. Ao contrário disso. Técnico e administrativo estão trabalhando sem sorrir. Nós temos de fazê-los voltar a sorrir. No hospital é uma barbaridade o que está acontecendo lá. Também nas unidades, como aqui, aqui o exemplo,"
+ },
+ {
+ "id_global": 203,
+ "fonte": "3o_debate",
+ "id_local": 51,
+ "timecode": "02:11:17",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto Sallessoubemos que durante o período de 30 horas, alguns servidores não podiam fazer as 30 horas. Isso é uma coisa absurda. Aliás, nós vamos resgatar o que já foi aprovado no Conselho Universitário, da comissão de assédio, que está engavetada e não foi implantada. Assédio em toda sorte, em toda universidade."
+ },
+ {
+ "id_global": 204,
+ "fonte": "3o_debate",
+ "id_local": 52,
+ "timecode": "02:12:20",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEu gostaria de continuar com o assunto que foi tratado aqui sobre a valorização dos servidores e também direcionar, já que nós estamos aqui em volta redonda, justamente para a questão daqui, quais foram os ganhos, os benefícios, qual a política que houve,"
+ },
+ {
+ "id_global": 205,
+ "fonte": "3o_debate",
+ "id_local": 53,
+ "timecode": "02:12:50",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallescomo acabou de dizer, de incentivo aos servidores. Dessa unidade, tanto da vila quanto da terra."
+ },
+ {
+ "id_global": 206,
+ "fonte": "3o_debate",
+ "id_local": 54,
+ "timecode": "02:16:14",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesBom, eu queria reportar a nossa criação, a reitoria itinerante, que era um mecanismo importante de ouvir os segmentos, inclusive os técnicos administrativos, sobre as questões mais importantes para eles naquele momento."
+ },
+ {
+ "id_global": 207,
+ "fonte": "3o_debate",
+ "id_local": 55,
+ "timecode": "02:16:45",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesE foram muitas vindas aqui. O outro também mecanismo importante, como eu falei, é a ouvidoria, que foi considerada uma das melhores do Brasil, já foi a nossa ouvidoria. Tinha resposta muito rápida. E o terceiro, que eu vou voltar a falar, da comissão de assédio. Ela tem que ser instalada em todos os lugares. E eu considero, o que eu ouvi em várias unidades, inclusive aqui, do cerco que é feito a alguns servidores sobre algumas questões."
+ },
+ {
+ "id_global": 208,
+ "fonte": "3o_debate",
+ "id_local": 56,
+ "timecode": "02:17:24",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEntão, essa comissão é fundamental que ela funcione. E ninguém tem que ter medo. Nós estamos nos tempos modernos. E outra questão também, que eu gostaria de falar, nós, na nossa gestão, nós dividimos dentro da pluralidade os cargos da reitoria, tanto de pró-reitoria e superintendente, entre técnico administrativo, professores, homens, mulheres."
+ },
+ {
+ "id_global": 209,
+ "fonte": "3o_debate",
+ "id_local": 57,
+ "timecode": "02:17:55",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesE pessoas até com necessidades especiais. O exemplo, inclusive, isso dentro da pluralidade, que o professor Antônio Calvo foi realmente meu pró-reitor de pesquisa, pós-graduação, pesquisa e inovação. Isso mostra a nossa visão plural da universidade. Isso é importante frisar que nós faremos de novo exatamente o que nós fizemos há oito anos atrás e continuamos no mandato seguinte, ou seja, nos dois mandatos."
+ },
+ {
+ "id_global": 210,
+ "fonte": "3o_debate",
+ "id_local": 58,
+ "timecode": "02:21:08",
+ "topicos": "Geral",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesMuito boa pergunta, né? Nós mantivemos durante os dois mandatos uma relação de cordialidade, não foi só com a TULF e SINTULF, também com o DCR. Nós tínhamos uma relação, eu fui o único reitor que fiz quatro audiências públicas. Eu não conheço mais nenhum reitor que tenha feito. Então, a relação foi sempre ouvindo tanto a TULF, SINTULF e o DCR. Tanto é verdade que nós acabamos, a única reforma que eu lembro que tenha ocorrido no DCR foi na nossa gestão."
+ },
+ {
+ "id_global": 211,
+ "fonte": "3o_debate",
+ "id_local": 59,
+ "timecode": "02:21:44",
+ "topicos": "ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesInclusive, tinha problema estrutural. Nós fizemos uma reforma geral. O SINTULF foi uma relação que toda vez que iria a uma reunião eram recebidos. Não mexi no espaço. O espaço que eles tinham na universidade. Eu entendia que o movimento tem uma dinâmica própria e ADUFF também, toda vez que eu fui solicitado a conversar com o sindicato, nós fizemos. E quando eu estava na comissão em Brasília sobre educação superior, nós convidamos todos os sindicatos para conversar."
+ },
+ {
+ "id_global": 212,
+ "fonte": "3o_debate",
+ "id_local": 60,
+ "timecode": "02:22:22",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesNós chamamos a Andes, Fazubra, Uni teve presente, outros sindicatos presentes. Então, nós chamamos para conversar todos os entes administrativos e políticos existentes na época. Então, minha relação foi sempre cordial e vai continuar a ser com todos esses entes. Agora, quanto à questão da diminuição do..."
+ },
+ {
+ "id_global": 213,
+ "fonte": "3o_debate",
+ "id_local": 61,
+ "timecode": "02:22:53",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesAntônio Pedro, eu também gostaria de dizer aqui claramente que existe... Eu, como membro permanente do Conselho Universitário, eu pedi a instalação de uma comissão para estudar o contrato da Ibser, depois de cinco anos, mesmo sabendo que todo contrato tem um fiscal. A minha proposta foi junto com a enfermeira Marça Carvalho e também com o funcionário Davi da Química. E a comissão está lá desde o final do ano, presidido pelo diretor da Faculdade de Medicina, e nós estamos aguardando o retorno do que vai dizer a comissão sobre o contrato da Ibser, se está sendo cumprida as cláusulas ou não, depois de cinco anos."
+ },
+ {
+ "id_global": 214,
+ "fonte": "3o_debate",
+ "id_local": 62,
+ "timecode": "02:23:48",
+ "topicos": "Hospital/EBSERH",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesNós sabemos que não está sendo cumprida, obviamente. Porque uma das cláusulas... Uma das cláusulas era contratar pessoal suficiente, depois de um ano, e abrir leitos. Não contratou o suficiente. E fechou leitos. Agora, uma providência tem que ser tomada a partir daí, formar uma comissão imediata do hospital, da faculdade de medicina e resolver."
+ },
+ {
+ "id_global": 215,
+ "fonte": "3o_debate",
+ "id_local": 63,
+ "timecode": "02:26:16",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesO Wilson, você falou do Futuris, eu quero recordar que foi nossa comissão na Câmara dos Deputados que nós conseguimos sepultar o Futuris, tanto na comissão da Câmara quanto no Senado. E dissemos claramente ao ministro e soubemos que teve um ex-reitor que foi apoiar o Futuris, ex-reitor da Universidade Federal Fluminense. Quero dizer que tudo que nós estamos falando aqui e falamos sobre o nosso..."
+ },
+ {
+ "id_global": 216,
+ "fonte": "3o_debate",
+ "id_local": 64,
+ "timecode": "02:26:50",
+ "topicos": "Hospital/EBSERH|ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesSobre o nosso programa, consta do relatório de gestão UFF 2006-2014, que pode só botar no Google e vocês vão ver tudo que aconteceu. E a outra questão, que nós saímos em 2014, não existe EBSERH sem reunião do Conselho Universitário, que foi feito em março de 2016, e sem assinatura de contrato. É só botar no Google também, contrato UFF-EBSERH abril de 2016, aí vão ter a resposta."
+ },
+ {
+ "id_global": 217,
+ "fonte": "3o_debate",
+ "id_local": 65,
+ "timecode": "02:41:23",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesQuero agradecer a coordenação, agradecer a direção aqui presente, a todos que estão nos assistindo aqui presentes e através do nosso canal, aos debatedores aqui, os candidatos, e dizer que nós não prometemos, nós fizemos e vamos fazer. Foram investimentos de 380 milhões, o mais audacioso de todas as universidades."
+ },
+ {
+ "id_global": 218,
+ "fonte": "3o_debate",
+ "id_local": 66,
+ "timecode": "02:41:58",
+ "topicos": "ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesObrigado. Nós construímos 125 prédios e 140 reformas. 180 mil metros quadrados de área construída, quando em 50 anos a UFF tinha 240 mil. Então, nós não estamos prometendo. Aqui foram investimentos de mais de 30 milhões de reais. Esses três blocos foram construídos na nossa época. E não adianta algumas pessoas andarem falando por aí que o dinheiro é fácil."
+ },
+ {
+ "id_global": 219,
+ "fonte": "3o_debate",
+ "id_local": 67,
+ "timecode": "02:42:29",
+ "topicos": "Governança/PDI",
+ "classe": "incomodado",
+ "escore": 3,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesCom o dinheiro é fácil, não. Deu certo porque botamos no PDI, na Comissão de Metas. E o dinheiro, quando tem uma quantidade grande, é vigiado por todos. É vigiado pelos órgãos de controle. E não é fácil. São muitos pedidos, muita coisa ao mesmo tempo. Aí a gente escuta, com o dinheiro é fácil. Sem dinheiro, que é difícil. Não. Se você é o comandante do navio e não souber qual o porto que vai atingir, você fica..."
+ },
+ {
+ "id_global": 220,
+ "fonte": "3o_debate",
+ "id_local": 68,
+ "timecode": "02:43:00",
+ "topicos": "Mobilidade/BuzUFF",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesderiva e pode causar um acidente. A outra questão que eu queria falar é que nós vamos brigar pelo passe livre, sim. Eu vou dizer por quê. Porque a UFF leva desenvolvimento social e econômico para oito municípios e a composição do passe livre, o passe, normalmente, a passagem é subsidiada pelo Estado. E nada mais do que justo da UFF, pleitear para os seus alunos, ainda mais no momento de carestia,"
+ },
+ {
+ "id_global": 221,
+ "fonte": "3o_debate",
+ "id_local": 69,
+ "timecode": "02:43:30",
+ "topicos": "Mobilidade/BuzUFF",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto Salleso passe livre. Isso é fundamental, na nossa opinião, na nossa visão. E nós vamos fazer. Nós fizemos e vamos fazer muito mais coisa por essa universidade. Votem na chapa 3, UFF plural, democrático. Agora, a professora Isabel."
+ },
+ {
+ "id_global": 222,
+ "fonte": "4o_debate",
+ "id_local": 1,
+ "timecode": "00:13:15",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesBoa noite a todos e a todas, aos candidatos presentes, a minha vice. Meu nome é Roberto Salles, eu tenho a pele morena, cabelo escuro, uso óculos, tenho 1,86m. Eu tenho, entre tempo de estudante e professor, tenho 45 anos de UFF. Então, eu tenho uma gratidão pela UFF, sou professor do departamento de microbiologia e parasitologia. E no dia de hoje nós queremos tratar alguns assuntos que eu..."
+ },
+ {
+ "id_global": 223,
+ "fonte": "4o_debate",
+ "id_local": 2,
+ "timecode": "00:13:48",
+ "topicos": "30h/Teletrabalho|ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEu acho pertinente a questão das 30 horas com ponto biométrico e teletrabalho. Gostaríamos também de abordar a questão do assédio moral. Gostaria de abordar... A questão do Morro do Graguatá, a Ibser, a manutenção dos nossos prédios, nossos aparelhos, término das obras e assistência estudantil. E, por último, a capacitação e qualificação do corpo técnico e do corpo docente também."
+ },
+ {
+ "id_global": 224,
+ "fonte": "4o_debate",
+ "id_local": 3,
+ "timecode": "00:14:23",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesA universidade cresceu muito, a universidade realmente é pujante, é uma das maiores do país, principalmente em entrada de alunos, mas multiplicou por quatro a pesquisa e pós-graduação na nossa gestão. Então, nós estamos aqui justamente pedindo apoio a todos para a chapa 3 UFF Plural Democrática, porque entendemos que eu e a professora Isabel temos a melhor proposta."
+ },
+ {
+ "id_global": 225,
+ "fonte": "4o_debate",
+ "id_local": 4,
+ "timecode": "00:14:53",
+ "topicos": "30h/Teletrabalho|Eleições/Processo",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallespara dar continuidade ao crescimento da nossa universidade. Eu quero dizer... que aqui nós não temos adversários nem inimigos. Nós temos pessoas com pontos de vista diferentes, e é assim que nós vamos tratar dessa eleição até o final, com tranquilidade e observando tudo o que acontece. Muito obrigado."
+ },
+ {
+ "id_global": 226,
+ "fonte": "4o_debate",
+ "id_local": 5,
+ "timecode": "00:23:18",
+ "topicos": "ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Antônio ClaudioEntão, a gente gostaria de perguntar à Chapa 3 quais são as políticas para a consolidação da expansão, num cenário completamente ao inverso do que foi a experiência do reitor anterior. Então, a gente gostaria de saber quais são as propostas concretas para esse processo de consolidação com a perspectiva de futuro. Obrigado."
+ },
+ {
+ "id_global": 227,
+ "fonte": "4o_debate",
+ "id_local": 6,
+ "timecode": "00:23:42",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "Speaker 2São três minutos, por favor."
+ },
+ {
+ "id_global": 228,
+ "fonte": "4o_debate",
+ "id_local": 7,
+ "timecode": "00:23:44",
+ "topicos": "Governança/PDI",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesObrigado pela pergunta. Mas nós falamos de passado, presente e futuro. Tem que ser falado. É tentar minimizar o investimento de R$ 380 mil, E que nós colocamos dentro do PDI, não fizemos nada na nossa cabeça, por isso que deu certo. Nós levamos a universidade para oito municípios. Os alunos vinham estudar aqui em Niterói."
+ },
+ {
+ "id_global": 229,
+ "fonte": "4o_debate",
+ "id_local": 8,
+ "timecode": "00:24:16",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesE nós colocamos a universidade nesses municípios. Alguns municípios já tinham curso, por exemplo, Campos, que tinha um curso de serviço social há 40 anos. Nós ampliamos para mais cinco cursos. Em Volta Redonda, tinham quatro engenharias. Criamos mais uma e mais oito cursos. Então, foi realmente um movimento muito grande, mas nada saiu da nossa cabeça, não dei nenhum palpite para nada. Foi amplamente discutida por todos. E, obviamente, a universidade expandiu bastante."
+ },
+ {
+ "id_global": 230,
+ "fonte": "4o_debate",
+ "id_local": 9,
+ "timecode": "00:24:49",
+ "topicos": "ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesE tivemos algumas obras que não conseguimos terminar, apesar da quantidade imensa de obras que nós entregamos. E cada reitor faz sua parte. O senhor faz, dentro da sua gestão, o que acha melhor. Nós vamos terminar tudo o que nós iniciamos, sem sombra de dúvida. A UFF leva desenvolvimento econômico e social para oito municípios. Nada mais justo que todos os municípios colaborarem, também os prefeitos,"
+ },
+ {
+ "id_global": 231,
+ "fonte": "4o_debate",
+ "id_local": 10,
+ "timecode": "00:25:19",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesassim também como o governo do Estado e até a Assembleia Legislativa, através dos deputados estaduais e até a bancada do Rio de Janeiro. Então, nós vamos trabalhar procurando essas parcerias, mesmo em momentos difíceis de restrição orçamentária. A restrição orçamentária é uma realidade, mas nós temos que trabalhar com o que nós temos. Obviamente que nós estamos trabalhando com a perspectiva de ter um governo favorável para frente."
+ },
+ {
+ "id_global": 232,
+ "fonte": "4o_debate",
+ "id_local": 11,
+ "timecode": "00:25:54",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesE quero já dizer que a ideia de cobrar mensalidade é mais uma loucura. De alguns parlamentares, que isso se repete a todos os anos, que isso aí não vão conseguir, porque a universidade precisa de investimento, educação é investimento, educação não é mercadoria. Então, isso aí não vai dar certo, não vai dar cola, e a PEC já saiu até de circulação, porque ninguém vai aceitar isso."
+ },
+ {
+ "id_global": 233,
+ "fonte": "4o_debate",
+ "id_local": 12,
+ "timecode": "00:26:26",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesQueria saber se a professora Isabel queria complementar alguma coisa."
+ },
+ {
+ "id_global": 234,
+ "fonte": "4o_debate",
+ "id_local": 13,
+ "timecode": "00:29:16",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesÉ, bom, eu falei aqui que cada reitor faz a sua parte, coloca, um tijolo, vamos dizer assim, mas o, reitor anterior, que você foi vice, pelo que eu, pude perceber, ele não colocou nenhum tijolo dentro da universidade. Pelo contrário, fez dívidas abertas, e nós temos documentos sobre isso, as dívidas que ele fez. Mas eu acho que está certo, cada um tem que procurar os seus caminhos, nós sabemos os caminhos, já acabei."
+ },
+ {
+ "id_global": 235,
+ "fonte": "4o_debate",
+ "id_local": 14,
+ "timecode": "00:29:47",
+ "topicos": "ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto Sallesde dizer os caminhos que nós vamos seguir. E eu acho que a UFF avançou bastante, o que precisa realmente agora é uma consolidação, terminar o prédio. da química, da farmácia, né? Você falou aí da medicina, mas ficou parado, sei lá, seis anos agora que retomou, de campos a mesma coisa, né? E eu acho que cada um realmente tem que se comprometer a terminar tudo que ficou para trás. Agora, foram 25 prédios entregues e 140 reformas,"
+ },
+ {
+ "id_global": 236,
+ "fonte": "4o_debate",
+ "id_local": 15,
+ "timecode": "00:30:18",
+ "topicos": "Geral",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesné? Pouca coisa nova. Muito obrigado."
+ },
+ {
+ "id_global": 237,
+ "fonte": "4o_debate",
+ "id_local": 16,
+ "timecode": "00:31:23",
+ "topicos": "Acessibilidade",
+ "classe": "incomodado",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEu vou perguntar para a chapa 2, sobre os três termos colocados dentro de uma mesma pergunta, gostaria de saber qual a visão de vocês em relação a isso, sempre uma visão da inclusão dentro da universidade, que nossos alunos precisam entrar na universidade, não basta entrar, tem que cursar e se formar, e para isso precisa de todo o apoio para essa política de inclusão. Então, é essa a pergunta."
+ },
+ {
+ "id_global": 238,
+ "fonte": "4o_debate",
+ "id_local": 17,
+ "timecode": "00:35:29",
+ "topicos": "Acessibilidade|Mobilidade/BuzUFF|ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesPode. Isso me fez lembrar, no momento do Reúne, que nós atendemos a reivindicação dos alunos de 50 anos, criamos a Moradia em Niterói e Rio das Ostras, ampliamos o Bandejão, criamos o BUZUFF, criamos o setor de acessibilidade e inclusão. Isabel depois vai dizer o mestrado que nós criamos. E, obviamente, quando eu entrei na UFF, tinha uma modalidade de Bolsa Social, que era a Bolsa de Trabalho."
+ },
+ {
+ "id_global": 239,
+ "fonte": "4o_debate",
+ "id_local": 18,
+ "timecode": "00:35:59",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesDepois criamos 13 modalidades de bolsa. Seguimos a UERJ, quando a UERJ criou cotas de 20% de pontuação para alunos de escolas públicas. Seguimos a UERJ e Mato Grosso, Universidade Federal. E depois veio o PNAD, nós colocamos nosso vestibular dentro do Enem-SISU. Em 2012, com a lei das cotas, nós integralizamos em dois anos, quando a lei falava quatro, já que nós saímos de 2014, foi 2013 e 2014."
+ },
+ {
+ "id_global": 240,
+ "fonte": "4o_debate",
+ "id_local": 19,
+ "timecode": "00:36:30",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesEntão, metade das nossas mais de 10 mil vagas foram justamente para atender a lei de cotas. Isso tudo consta do relatório de gestão UFF 2006-2014, está no Google. E aí não tem fake, é ali que está escrito com toda clareza. E a Isabel agora vai falar também do curso que nós criamos."
+ },
+ {
+ "id_global": 241,
+ "fonte": "4o_debate",
+ "id_local": 20,
+ "timecode": "00:58:11",
+ "topicos": "Geral",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesPode iniciar, professor. A pergunta é, coordenou uma comissão na Câmara dos Deputados, que nós tínhamos ex-reitoras como Ana Lúcia Gazola, que todo mundo conhece muito bem, na Universidade Federal de Minas Gerais, Tompes Marins de Campina Grande, que é uma das universidades que tem o maior número de patentes, e Eliane Supersto Amapá, que é uma pessoa que trabalha com pesquisa para a graduação, e foram os dois consultores legislativos de alto nível da Câmara dos Deputados."
+ },
+ {
+ "id_global": 242,
+ "fonte": "4o_debate",
+ "id_local": 21,
+ "timecode": "00:58:42",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesE lá, obviamente, nós fizemos algum trabalho. Um deles, um dos trabalhos, foi colocar em circulação o projeto de autonomia. Eram quatro ou cinco projetos tramitando, estavam lá a marcha lenta, e nós... Desencavetamos o projeto do Gastão Vieira, anexamos os restantes e fizemos circular. Obviamente que a pandemia atrasou um pouco e o resultado nós estamos vendo aí. A universidade, apesar de ser garantida."
+ },
+ {
+ "id_global": 243,
+ "fonte": "4o_debate",
+ "id_local": 22,
+ "timecode": "00:59:13",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallespelo artigo 207 da Constituição, que o reitor tem que fazer valer, por exemplo, no caso das 30 horas, eu iria ao Supremo, faria valer a autonomia universitária, que não foi feita. E, aliás, eu tenho um documento de 2017, que o ex-reitor, que o atual é vice, já sabia da colocação do ponto eletrônico. Então, não foi nenhuma surpresa,"
+ },
+ {
+ "id_global": 244,
+ "fonte": "4o_debate",
+ "id_local": 23,
+ "timecode": "00:59:43",
+ "topicos": "Eleições/Processo",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesporque o documento já tramitava. Então, o que eu quero dizer é que essa foi uma ação importante, para termos realmente autonomia total, como tem as paulistas. As paulistas têm vinculação e subvinculação, orçamentária, atrelada à arrecadação do CMS. Mas, independente disso, por exemplo, a UFF trouxe aí, num passado não muito distante, um procurador que não era dos quadros dos advogados da União que a UFF."
+ },
+ {
+ "id_global": 245,
+ "fonte": "4o_debate",
+ "id_local": 24,
+ "timecode": "01:00:17",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallestem. E ele fez aquela barbaridade de levar denúncias de todo o Conselho Universitário sobre o enquadramento daqueles servidores técnicos com a administrativa aposentados, que o Conselho, por unanimidade, aprovou. Inclusive, muitos dos membros que aprovaram fazem parte da gestão atual. Então, acho que é isso. Autonomia é o reitor fazer valer. Se nós fôssemos seguir tudo que os órgãos de controle."
+ },
+ {
+ "id_global": 246,
+ "fonte": "4o_debate",
+ "id_local": 25,
+ "timecode": "01:00:47",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto Sallesqueriam nos impor, nós não teríamos feito o que fizemos em termos de crescimento da UFF. E algumas pessoas ficam minimizando. E é uma barbaridade realmente trazer alguém para o Conselho Universitário. momento como esse para fazer parte militar, para fazer parte do gabinete. Eu realmente acho isso um absurdo total. Eu, pelo menos, não faria isso. Eu tive uma relação muito forte com as forças armadas, mas uma relação de parceria e uma distância."
+ },
+ {
+ "id_global": 247,
+ "fonte": "4o_debate",
+ "id_local": 26,
+ "timecode": "01:03:35",
+ "topicos": "Hospital/EBSERH",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesO pior de tudo é que ele depois foi candidato pelo PFL, era bolsonarista, e o ex-reitor pousou lá do lado do Vontraube, apoiando o Futuris, que nossa comissão em Brasília, tanto na comissão da Câmara, quanto no Senado, sepultamos o Futuris. Isso que é mais irônico. Mas eu queria também aproveitar esse tempo e responder, porque existe isso. Há muitas coisas que podem ser facilmente comprovadas. A EBSERH, eu saí em 2014, novembro."
+ },
+ {
+ "id_global": 248,
+ "fonte": "4o_debate",
+ "id_local": 27,
+ "timecode": "01:04:07",
+ "topicos": "Hospital/EBSERH|ReUni/Infra",
+ "classe": "incomodado",
+ "escore": 5,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesA EBSERH, não existe EBSERH sem aprovação no Conselho Universitário e sem assinatura de contrato. Se botarem no Google, contrato UFF-EBSERH, vocês vão ver o que aconteceu. Foi uma reunião em março, com tropa de choque lá na imprensa do Estado, e depois em abril, assinatura do contrato. É só botar no Google que todos verão quem realmente assinou. Não existe EBSERH sem aprovação no Conselho e sem assinatura do contrato."
+ },
+ {
+ "id_global": 249,
+ "fonte": "4o_debate",
+ "id_local": 28,
+ "timecode": "01:44:56",
+ "topicos": "Hospital/EBSERH",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEu acho que nós temos que fazer valer a decisão. o Conselho Universitário. Já foi decidido que tem que instalar uma comissão e cabe ao reitor indicar os membros dessa comissão e fazer funcionar. As pessoas estão adoecendo em todos os lugares da UFF, inclusive no hospital. Então, nós temos que encarar essa questão de frente, não poder mais deixar passar. Então, o CUV decidiu que tem que pegar os membros e nomear."
+ },
+ {
+ "id_global": 250,
+ "fonte": "4o_debate",
+ "id_local": 29,
+ "timecode": "01:45:28",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallese a comissão tem que trabalhar e a universidade tomar as providências de acordo com o que for apurado. E outro instrumento que você falou muito bem, foi a ouvidoria que nós criamos e funcionou na plenitude, dando resposta a todos os segmentos, cobrava, porque tem um prazo legal para resposta. Senão, as pessoas vão se direcionar aos órgãos superiores de controle. Então, a ouvidoria tem um papel importante. Ela foi considerada..."
+ },
+ {
+ "id_global": 251,
+ "fonte": "4o_debate",
+ "id_local": 30,
+ "timecode": "01:46:00",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesUma das melhores do Brasil."
+ },
+ {
+ "id_global": 252,
+ "fonte": "4o_debate",
+ "id_local": 31,
+ "timecode": "01:50:46",
+ "topicos": "ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesNós temos visto aí muitas, nós temos visto o seguinte, tivemos oito anos, né, e quero dizer que o Reúne realmente hoje existe... Se existe alguma coisa realmente para se fazer dentro da universidade, temos que agradecer ao Reúne, que o Reúne transformou a nossa universidade. Isso que é grande verdade. Agora, eu queria saber o seguinte, eu estou vendo muitas movimentações de coisas que podiam ter sido colocadas já há alguns anos,"
+ },
+ {
+ "id_global": 253,
+ "fonte": "4o_debate",
+ "id_local": 32,
+ "timecode": "01:51:22",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallese só agora começa a sair uma série de coisas, inclusive inaugurações, reinaugurações, perto do momento eleitoral. Inclusive, instruções normativas para cá, para lá. Então, eu gostaria de saber do candidato, por que não foi feito ao longo desses anos, não vou dizer nem os quatro anos anteriores, ele era o vice, mas nesses quatro anos, por que agora perde o processo eleitoral, inclusive uma discussão sobre o morro do Craguatá, uma comissão."
+ },
+ {
+ "id_global": 254,
+ "fonte": "4o_debate",
+ "id_local": 33,
+ "timecode": "01:51:55",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesIsso que eu gostaria que ele explicasse, por gentileza."
+ },
+ {
+ "id_global": 255,
+ "fonte": "4o_debate",
+ "id_local": 34,
+ "timecode": "01:55:22",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesPode. Eu acho, professor, que nós temos que procurar realmente soluções. Mas a instrução normativa do Paulo Guedes é de 2020. E só agora foi implantada essa opção do teletrabalho. Nós temos que ter realmente opções para os nossos técnicos administrativos que têm que voltar a sorrir. Mas essa instrução é de 2020. E foi implantada agora, é experimental."
+ },
+ {
+ "id_global": 256,
+ "fonte": "4o_debate",
+ "id_local": 35,
+ "timecode": "01:55:53",
+ "topicos": "Eleições/Processo",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesE leva para o servidor todo o ônibus. E também... perde alguns direitos, eu acho que isso tem que ser muito bem explicado, eu sei que foi feito por técnico, a gente tem maior respeito por todos que trabalham, eu sempre defendi que a maior riqueza são as pessoas que trabalham na universidade e qualquer empresa é assim, e a universidade não é diferente, né? Então o que eu fico pensando é tudo assim, próximo, à eleição, né? E a questão."
+ },
+ {
+ "id_global": 257,
+ "fonte": "4o_debate",
+ "id_local": 36,
+ "timecode": "01:56:24",
+ "topicos": "Geral",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallestambém lá do Morro de Caraguatá, nós sabemos, o senhor só era o vice do reitor anterior e houve toda uma movimentação para entregar uma área de preservação para uma, empresa, uma empreiteira, para construir oito blocos de apartamento em cima das engenharias, da arquitetura, da computação. Isso aí no mínimo seria prejudicial, né? Por circulação de vento, barulho, e nós tivemos que."
+ },
+ {
+ "id_global": 258,
+ "fonte": "4o_debate",
+ "id_local": 37,
+ "timecode": "01:56:55",
+ "topicos": "Eleições/Processo",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesarticular a sociedade, como eu tive presente também, para ser contra essa medida que seria danosa para a universidade. Então, realmente, nós temos que procurar o melhor. Mas nós temos que fazer isso concatenadamente. Não podemos chegar, o senhor participou de oito anos da gestão, porque foi vice e agora reitou quatro anos, poderia ter visto isso com toda tranquilidade, explicado bem antes e não próximo da eleição,"
+ },
+ {
+ "id_global": 259,
+ "fonte": "4o_debate",
+ "id_local": 38,
+ "timecode": "01:57:28",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesquando aconteceu da vez passada, das 30 horas, que já existia até um documento lá, circulando sobre o ponto eletrônico."
+ },
+ {
+ "id_global": 260,
+ "fonte": "4o_debate",
+ "id_local": 39,
+ "timecode": "02:08:56",
+ "topicos": "Geral",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesPosso começar? Pode começar. O assunto está sendo discutido por várias instituições federais de ensino superior, inclusive a Fasubra, a CIS. Então, porque é um assunto que tem que ser discutido com clareza para saber como vai ser apresentado aos nossos servidores técnico-administrativos. Então, muitos questionamentos existem de técnicos que não são respondidos."
+ },
+ {
+ "id_global": 261,
+ "fonte": "4o_debate",
+ "id_local": 40,
+ "timecode": "02:09:30",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesEntão, no meu ponto de vista, houve uma precipitação, já que a instrução normativa do Guedes é 2020 e agora próximo do período de escolha de reitor está sendo apresentado e as pessoas não estão realmente cientes do que vai acontecer, em especial na perda de direitos. Quem tem, vão perder o... Quem tem saúde... Pobridade, o raio-x perde, quem tem adicional noturno vai perder, vale transporte."
+ },
+ {
+ "id_global": 262,
+ "fonte": "4o_debate",
+ "id_local": 41,
+ "timecode": "02:10:06",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesE quando eu falei, é por tempo determinado, inicialmente por seis meses, então pode ser revogado. Eu acho que esse assunto mexe com a vida das pessoas, né? E houve uma confusão no início entre biometria e ponto eletrônico, não precisava botar biometria. E eu li o documento de 2007, o ex-reitor respondendo ao Ministério Público, uma procuradora, falando justamente que estava comprando as máquinas para poder colocar a biometria."
+ },
+ {
+ "id_global": 263,
+ "fonte": "4o_debate",
+ "id_local": 42,
+ "timecode": "02:10:40",
+ "topicos": "Eleições/Processo",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEntão, o assunto, antes da eleição de 2018, o assunto já era conhecido da universidade. Nós estamos até com uma cópia desse documento. Eu só acho o seguinte, as coisas têm que ser colocadas com clareza, não de cima para baixo, do baixo para cima. Há foram os técnicos. Da pró-reitoria que estudaram, ótimo. Nós temos, eu sempre falei que a maior riqueza que nós temos são as pessoas que trabalham, mas tinha que conversar com os técnicos administrativos que são os interessados pela situação e não foram consultados. Se fosse uma coisa simples, as instituições federais de Sinafazubra não estariam discutindo isso, a SIS."
+ },
+ {
+ "id_global": 264,
+ "fonte": "4o_debate",
+ "id_local": 43,
+ "timecode": "02:11:20",
+ "topicos": "30h/Teletrabalho|Eleições/Processo",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesEntão, foi uma medida precipitada, próximo da eleição, e aí a cada um interpreta da maneira que quiser, que poderia ser discutido melhor para depois ser aplicado, com toda tranquilidade. Então, esse é o nosso ponto de vista."
+ },
+ {
+ "id_global": 265,
+ "fonte": "4o_debate",
+ "id_local": 44,
+ "timecode": "02:14:17",
+ "topicos": "EAD/Remoto|ReUni/Infra",
+ "classe": "incomodado",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesÉ, os... Pode começar? Olha, os servidores técnicos administrativos têm trabalhado realmente sobre tensão, tem que voltar a sorrir, por exemplo, foi falado aqui elevadores, né? Os elevadores são todos sucateados, né? Falaram de um ou dois prédios que não tinham elevador, eu não tenho ciência disso, mas todos os elevadores, de qualquer campo você vai, não tem manutenção, tem lugar que só funciona um de quatro, o Antônio Pedro já caiu algumas vezes pra parte de baixo, né?"
+ },
+ {
+ "id_global": 266,
+ "fonte": "4o_debate",
+ "id_local": 45,
+ "timecode": "02:14:49",
+ "topicos": "Geral",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesFelizmente não atingiu ninguém, né? E todos os elevadores foram recuperados lá atrás, né? Houve continuidade e manutenção, essa que é a verdade. Mas o... A discussão sobre o tema em questão, o teto de trabalho, deveria se aguardar a discussão das outras universidades, do próprio Fasubra, da própria comissão interna, a CIS, entendeu? E aí sim conversar com os técnicos administrativos."
+ },
+ {
+ "id_global": 267,
+ "fonte": "4o_debate",
+ "id_local": 46,
+ "timecode": "02:15:21",
+ "topicos": "Geral",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallespara falar qual foi a solução encontrada e não uma implantação de cima para baixo. E até também, eles estão sem comissão de assédio moral, né? Que nós esperamos dois anos..."
+ },
+ {
+ "id_global": 268,
+ "fonte": "4o_debate",
+ "id_local": 47,
+ "timecode": "02:21:13",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEu acho que essa questão é uma questão que você falou muito importante. Eu acho que está havendo um prejuízo muito grande para o segmento técnico-administrativo. Isso leva a um conflito entre segmentos desnecessários. O que tinha que ser feito foi realmente, o que teria que ser feito é usar as prerrogativas que foram faladas aqui e levar isso para o Supremo."
+ },
+ {
+ "id_global": 269,
+ "fonte": "4o_debate",
+ "id_local": 48,
+ "timecode": "02:21:43",
+ "topicos": "ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesIsso aí levar 20 anos para ser resolvido e não rapidamente sucumbir ao Ministério Público. O questionamento. Se fosse ligar para todos os questionamentos do Ministério Público, nós não faríamos obra nenhuma, que é todo momento. Inclusive, nossas obras foram paralisadas lá atrás pelo Ministério Público. Então, e hoje, se tem alguma coisa para ser colocada para frente, como tem falado, agradeça o passado, não pode esquecer,"
+ },
+ {
+ "id_global": 270,
+ "fonte": "4o_debate",
+ "id_local": 49,
+ "timecode": "02:22:13",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallesporque o passado alavancou o presente e o futuro. Então, é isso. Terminou."
+ },
+ {
+ "id_global": 271,
+ "fonte": "4o_debate",
+ "id_local": 50,
+ "timecode": "02:33:31",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesPode. Queria agradecer ao professor Fábio pela gentileza da pergunta. E fiquei feliz agora que o reitor, pela primeira vez, reconheceu, ele falou, a maior universidade federal do país, mas já era em 2014. Então, pelo menos um reconhecimento. Eu acho que isso é muito bom. E também dizer que o fato do reitor ter sido meu pró-reitor e depois ter sido... vice do anterior."
+ },
+ {
+ "id_global": 272,
+ "fonte": "4o_debate",
+ "id_local": 51,
+ "timecode": "02:34:01",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallese desse, na verdade, ele nunca me perguntou nada sobre a gestão, nem ele me pediu nada, nem eu informei nada a ele. Então, a responsabilidade da gestão é dele, exclusivamente. Então, o fato de termos convivido em algum momento como pró-reitor e reitor, não significa que nós temos responsabilidade na gestão. Então, é isso. Então, agradeço o reconhecimento, reitor, pela primeira vez. Eu acho que, acho que antes tarde do que nunca. Mas, falando."
+ },
+ {
+ "id_global": 273,
+ "fonte": "4o_debate",
+ "id_local": 52,
+ "timecode": "02:34:32",
+ "topicos": "Acessibilidade|ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallesaí da questão do... Primeiro que nós temos que terminar a obra, as obras. E, quando vocês falam do Reúne, vocês falam assim, eu acho que um pouco, descaso. O Reúne foi o maior projeto de inclusão do governo Lula, com o ministro Hernando Haddad e Paim, que proporcionou que a UFF realmente desse um salto, mas não foi só no espaço físico. Foi também no número de alunos de graduação e após... pós-graduação. Afinal de contas, nós tínhamos."
+ },
+ {
+ "id_global": 274,
+ "fonte": "4o_debate",
+ "id_local": 53,
+ "timecode": "02:35:03",
+ "topicos": "Cultura/Cinema|ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallescomplementação de bolsa por três anos de todos os cursos mestrado e doutorado. Nós vamos terminar as obras. Se vocês não conseguirem terminar cinco obras, nós entregamos 25 prédios. Fizemos 140 reformas. O cinema é novo. Se vocês não conseguirem entregar, nós vamos entregar. Nós não somos daquele quanto pior, melhor não. Quanto melhor, melhor. Eu acho que cada um realmente faz o que pode e bota seu tijolo. Então, nós vamos fazer isso. Nós vamos terminar."
+ },
+ {
+ "id_global": 275,
+ "fonte": "4o_debate",
+ "id_local": 54,
+ "timecode": "02:35:34",
+ "topicos": "Hospital/EBSERH|ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallestudo que não for terminado. E foram só cinco obras. Vou terminar o prédio da química, vou terminar o prédio da matemática. Se a medicina não ficar pronto, nós vamos entregar campos. E assim sucessivamente. Vamos ter que também, reformar alguns prédios que já tem tantos anos que não sofrem nenhuma reforma. Tem que ser reformado. Os elevadores são exemplos. A coisa que mais se pedia no hospital era conserto dos elevadores."
+ },
+ {
+ "id_global": 276,
+ "fonte": "4o_debate",
+ "id_local": 55,
+ "timecode": "02:36:06",
+ "topicos": "Hospital/EBSERH",
+ "classe": "incomodado",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesNós deixamos todos os elevadores funcionando. E hoje a questão dos elevadores é um caos dentro da universidade, assim como o ar-condicionado também. Então, o que nós vamos fazer concretamente é isso. O que vocês não conseguiram fazer, nós vamos pegar dali e vamos colocar para frente. É isso. Nós não somos aqueles que achamos que estamos torcendo o contrário. Aliás, minha participação no Conselho Universitário, que eu pedi, inclusive, a comissão para rever o contrato da EBSERH,"
+ },
+ {
+ "id_global": 277,
+ "fonte": "4o_debate",
+ "id_local": 56,
+ "timecode": "02:36:38",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesque tem um fiscal e ninguém pediu até hoje. Eu tive que pedir junto com a Márcia e o Davi. Nós vamos fazer isso. No Conselho eu sempre fui tranquilo."
+ },
+ {
+ "id_global": 278,
+ "fonte": "4o_debate",
+ "id_local": 57,
+ "timecode": "02:39:04",
+ "topicos": "Governança/PDI|ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesNós temos que falar a verdade total, não pode ser uma verdade em parte. O que o professor quis falar é que algumas unidades, democraticamente, não aderiram ao Reúne. Algumas não aderiram, de jeito nenhum, e outras não aderiram em parte. Depois aderiram, numa segunda fase, e eu não decidi nada. Quem decidiu foi a comissão de métodos do PDI, presidida pelo diretor da época da engenharia, professor Emanuel Paiva de Andrade."
+ },
+ {
+ "id_global": 279,
+ "fonte": "4o_debate",
+ "id_local": 58,
+ "timecode": "02:39:35",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 6,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesEntão, o que acontece foi isso. Agora, quem não aderiu, aderiu no segundo momento, pediu, por exemplo, vagas de professores, de técnicos, uma reforma aqui, outra ali. E eu não decidi absolutamente nada, foi 100% democrático. Agora, nós temos o projeto, sim. As engenharias estarão... Na linha de frente da nossa gestão. Nós vamos recuperar o projeto. O projeto que tem lá de ampliação, vamos fazer. E sem nenhum mandato, nós colocamos uma emenda."
+ },
+ {
+ "id_global": 280,
+ "fonte": "4o_debate",
+ "id_local": 59,
+ "timecode": "02:40:05",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesde R$ 500 mil para as engenharias. Está na mão do coordenador, é o diretor atual. Então, nós estamos pensando em tudo, sim. Estamos pensando no futuro. Agora, quando for falar as coisas, tem que falar a verdade. O reitor não deu uma opinião qual seria a obra que ia ali."
+ },
+ {
+ "id_global": 281,
+ "fonte": "4o_debate",
+ "id_local": 60,
+ "timecode": "02:44:51",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesBom, eu queria também cumprimentar a todos os participantes aqui da Chapa. Todos estão trabalhando nesse momento, a coordenação e dizer que nós estamos muito felizes em poder participar dessas discussões, dizer que a chapa 3U Federal Democrática realmente está muito animada com a repercussão que vem ocorrendo."
+ },
+ {
+ "id_global": 282,
+ "fonte": "4o_debate",
+ "id_local": 61,
+ "timecode": "02:45:25",
+ "topicos": "30h/Teletrabalho",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesNós estamos procurando manter um nível elevado, não temos nenhum inimigo aqui, nem adversários, nós temos um ponto de vista diferente, mas prezamos pela verdade. A questão da comissão de assédio moral, que tem que ser complementada, nós pedimos ao SintUFF que indicasse o nome, como demorou e acabou o mandato, e eles mandaram já há dois anos agora para formar a comissão. Eu acho importante sim formar essa comissão, nesse momento pós-covid."
+ },
+ {
+ "id_global": 283,
+ "fonte": "4o_debate",
+ "id_local": 62,
+ "timecode": "02:46:02",
+ "topicos": "Hospital/EBSERH",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesAs pessoas estão sob tensão no hospital e ninguém pode ter medo de uma comissão de assédio moral. Acho que a universidade deve isso a todos, não só aos técnicos administrativos, como também a todos os docentes e alunos, todos os nossos estudantes. Fico feliz de ter apresentado aqui um pouco da história do passado, mas estamos também olhando para o futuro, estamos no presente olhando para o futuro."
+ },
+ {
+ "id_global": 284,
+ "fonte": "4o_debate",
+ "id_local": 63,
+ "timecode": "02:46:34",
+ "topicos": "Governança/PDI|ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesE gostei muito do reconhecimento que houve pela primeira vez da importância do Reúne. E foi falado muito bem, o Reúne não teve dono, não. Nós que apresentamos o projeto mais ousado, mas colocamos tendo PDI. Afinal de contas, o plano de desenvolvimento institucional é muito importante, porque todos participam e todos apontam prioridades. Isso é uma maneira de... Discutir com a comunidade os três segmentos. O que é importante? Não tirar do bolso, da cartola."
+ },
+ {
+ "id_global": 285,
+ "fonte": "4o_debate",
+ "id_local": 64,
+ "timecode": "02:47:06",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallese depois ficar falando que discutiu com a comunidade. O exemplo está aí. O teletrabalho. Enquanto algumas universidades ainda discutem, veem como vai fazer, a Fasubra também os servidores cheios de dúvidas, perguntam, o que nós temos que fazer é isso. É dar oportunidade."
+ },
+ {
+ "id_global": 286,
+ "fonte": "5o_debate",
+ "id_local": 1,
+ "timecode": "00:07:21",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesMeu nome é Roberto Salles, tenho 1,86m, cabelo ondulado, uso óculos, pele morena. Sou professor do Departamento de Microbiologia e Parasitologia do Instituto Biomédico. Eu fico muito à vontade para falar aqui. Primeiro, eu queria cumprimentar todos os candidatos, o Wilson, o Vladimir, o Antônio Claudio, espero melhoras, sinceras recuperações rápidas, o Fábio, o Silvio, o Isabel, a Elisabeth."
+ },
+ {
+ "id_global": 287,
+ "fonte": "5o_debate",
+ "id_local": 2,
+ "timecode": "00:07:53",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesA Aline, todos que estão nos assistindo. Eu estou muito à vontade para falar aqui porque nós estamos... Estamos falando por algumas unidades da UFF localizada nos municípios, em que tivemos a oportunidade de levar a universidade para esses municípios, porque o fluxo era o inverso, os alunos tinham que ir na UFF para estudar. Então, conseguimos realmente enraizar a universidade com concursos, fixação de professores, funcionários, inclusive, na grande totalidade, alunos nesses municípios."
+ },
+ {
+ "id_global": 288,
+ "fonte": "5o_debate",
+ "id_local": 3,
+ "timecode": "00:08:35",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesE não é pouca coisa, a UFF leva desenvolvimento social e econômico a esses municípios, leva também desenvolvimento para esses municípios, leva ensino não só de graduação, de pós-graduação, também ajuda em parcerias com vários municípios, com vários... Então, realmente, a Universidade Federal Fluminense faz acontecer. Quero dizer que fui muito honrado de ter ficado à frente da universidade."
+ },
+ {
+ "id_global": 289,
+ "fonte": "5o_debate",
+ "id_local": 4,
+ "timecode": "00:09:13",
+ "topicos": "Governança/PDI|Transparência/Orçamento",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto Sallesnum momento tão importante do governo Lula, em que tivemos a oportunidade de investir 380 milhões de reais em toda a Universidade Federal Fluminense. Eu acho que nós conseguimos fazer todo esse investimento porque colocamos os recursos dentro da comissão de metas do PDI. Eu acho que isso foi realmente muito acertado, porque o PDI funciona como orçamento participativo. Todos puderam discutir, todos puderam pleitear os seus projetos."
+ },
+ {
+ "id_global": 290,
+ "fonte": "5o_debate",
+ "id_local": 5,
+ "timecode": "00:09:48",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto Sallese depois eram aprovados pelo conselho universitário. Então, realmente, nesse primeiro momento, essa apresentação... que eu gostaria de fazer, dizer que eu fico muito feliz de falar... tanto com o segmento dos estudantes, dos técnicos administrativos, dos professores e também dos prestadores de serviço de todas essas unidades da UFF, realizadas nesses municípios. Muito obrigado."
+ },
+ {
+ "id_global": 291,
+ "fonte": "5o_debate",
+ "id_local": 6,
+ "timecode": "00:38:45",
+ "topicos": "Cultura/Cinema",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesA questão, Wilson, é que, nós começamos o entendimento de que, a universidade não é só, ensino, pesquisa, extensão e até também... assistência como decorrência desse tripé. A universidade vai muito além. Nós temos, obviamente, equipamentos culturais importantíssimos, temos também departamentos como o de arte, produção cultural,"
+ },
+ {
+ "id_global": 292,
+ "fonte": "5o_debate",
+ "id_local": 7,
+ "timecode": "00:39:16",
+ "topicos": "Cultura/Cinema",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallese temos também nas unidades fora de sede pessoas com propostas concretas, como aconteceu em Campos. Agora, acho que nós temos que respeitar, não ter nada. amarrado, dizendo assim eu tenho uma ideia boa, vou implantar. Acho que nós temos que ouvir, ouvir a comunidade, todas as propostas que vão no sentido de que as artes, a cultura e a produção cultural."
+ },
+ {
+ "id_global": 293,
+ "fonte": "5o_debate",
+ "id_local": 8,
+ "timecode": "00:39:47",
+ "topicos": "Cultura/Cinema",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto Sallespossam envolver toda a universidade, nós temos que ouvir a comunidade e incentivar tudo, que vier em termos de ideias, da comunidade. Acho isso uma coisa importante. Nós demos o primeiro passo humilde, que foi melhorar o nosso centro de arte, que é composto por um cinema, por um teatro, por uma galeria. Compramos o cinema Icaraí, que está parado desde aquela data."
+ },
+ {
+ "id_global": 294,
+ "fonte": "5o_debate",
+ "id_local": 9,
+ "timecode": "00:40:19",
+ "topicos": "Cultura/Cinema",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallesem que saímos, mesmo com o concurso de ideias feito, o projeto básico executivo. Agora, estamos falando aqui para as unidades fora de sede. Temos que incentivar todo o projeto que vier da comunidade no sentido de integrar todas as propostas que falam de arte, que falam de produção cultural, que falam também de teatro, de televisão, de cinema, de tudo."
+ },
+ {
+ "id_global": 295,
+ "fonte": "5o_debate",
+ "id_local": 10,
+ "timecode": "00:40:52",
+ "topicos": "Cultura/Cinema",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesAcho que não podemos já ter uma ideia preconcebida, que temos a melhor ideia. Como nós... Estivemos lá no nosso cinema, conversamos com todos lá, sobre o que nós podemos fazer no futuro. E, obviamente, que nós temos que ouvir toda essa comunidade. Não sei se a Isabel teria alguma coisa para colocar, por não."
+ },
+ {
+ "id_global": 296,
+ "fonte": "5o_debate",
+ "id_local": 11,
+ "timecode": "00:44:14",
+ "topicos": "Cultura/Cinema",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesEu lembro da EDUFF, que nós fizemos um acordo com o Banco do Brasil, fizemos aquela reforma maravilhosa. Colocamos, inclusive, a EDUFF fazendo parte de alguns lugares, através de uma banca. E houve uma regressão muito grande. A orquestra, depois de uma obra de quase 10 anos, qualquer obra, se não fizer manutenção, começa a ter problemas. E a orquestra, quando nós assumimos, estava em uma condição muito triste,"
+ },
+ {
+ "id_global": 297,
+ "fonte": "5o_debate",
+ "id_local": 12,
+ "timecode": "00:44:46",
+ "topicos": "Cultura/Cinema",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesquase não tinha músicos do quadro. E tivemos a oportunidade, com a sensibilidade do ministro Haddad, de fazer concurso para o quadro e também comprar instrumentos. Eu acho que... Eu acho que, por exemplo, Rio das Ostras, que tem um departamento de arte e produção cultural. Acho que as pessoas ali conhecem bastante. Acho que nós temos que incentivar. Não cabe ao reitor dizer o que é melhor para as artes e para a cultura. Cabe à comunidade que tenha."
+ },
+ {
+ "id_global": 298,
+ "fonte": "5o_debate",
+ "id_local": 13,
+ "timecode": "00:45:16",
+ "topicos": "Geral",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesprojetos serem apoiados. É isso. Já deu um minuto? Já."
+ },
+ {
+ "id_global": 299,
+ "fonte": "5o_debate",
+ "id_local": 14,
+ "timecode": "00:46:07",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesÉ a gestão de pessoas, uma coisa muito interessante. Eu gostaria de saber da chapa 2, o análise de como nós estamos na questão. da gestão de pessoas no sentido de, colocação do ponto biométrico, dessa mudança que teve de 30 para o ponto biométrico. Eu gostaria de saber da sua análise sobre essa situação."
+ },
+ {
+ "id_global": 300,
+ "fonte": "5o_debate",
+ "id_local": 15,
+ "timecode": "01:08:00",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesBom, eu fico muito feliz que o reitor esteja falando agora de debate, não apresentar nada pronto, a discussão foi muito interessante, mas nós estamos aqui em um debate para unidades como Petrópolis, como Friburgo, Pádua, então nós temos que falar antes de apresentar uma proposta de ensino inovador, temos que tratar primeiro da questão mínima de infraestrutura, de condições de trabalho e de estudos, condições de trabalho dos professores, dos técnicos administrativos e também de aprendizado desses alunos, então eu acho que é muito importante todos esses debates, mas as nossas unidades da UFF nos municípios, elas precisam de um apoio muito grande,"
+ },
+ {
+ "id_global": 301,
+ "fonte": "5o_debate",
+ "id_local": 16,
+ "timecode": "01:09:00",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallespara as condições mínimas, para depois nós pensarmos realmente em grandes projetos, que possam alavancar o nosso ensino. Como a Isabel falou muito bem, a vinculação da graduação com a pós-graduação é muito importante. Não existe, pós-graduação forte e graduação fraca. Ok."
+ },
+ {
+ "id_global": 302,
+ "fonte": "5o_debate",
+ "id_local": 17,
+ "timecode": "01:37:00",
+ "topicos": "ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesÉ, isso é uma questão que já ocorria até antes mesmo da ida, tanto do docente, do técnico, até do estudante. Até para os concursos, nós fizemos dentro do Reúne, preferencialmente para doutores, em alguns casos nós tivemos que colocar para assistente, porque não aparecia ninguém para ir para as unidades localizadas nos municípios em que a UFF cresceu, vamos dizer assim."
+ },
+ {
+ "id_global": 303,
+ "fonte": "5o_debate",
+ "id_local": 18,
+ "timecode": "01:37:36",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesMas, com o tempo, foi superado. Hoje nós temos unidades com corpo docente de alto nível em todos os sentidos. Muitas vagas foram preenchidas por doutores, criados cursos de pós-graduação, mas acontece que também... A questão da estrutura influencia... influencia na permanência tanto do professor, do técnico, desestimula um pouco. Eu acho que isso é uma questão que tem que ser tratada com atenção para manter esses docentes, a maioria de técnicos altamente qualificados, e mantê-los lá nas unidades para onde eles fizeram concurso, que afinal de contas o concurso foi feito nos municípios para poder enraizar os cursos ali."
+ },
+ {
+ "id_global": 304,
+ "fonte": "5o_debate",
+ "id_local": 19,
+ "timecode": "01:38:30",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallespara as pessoas terem, se possível, morar nos locais, inicialmente não, nos municípios, e a UFF poder levar o desenvolvimento econômico e social. Mas, de qualquer maneira, é natural que um ou outro professor técnico administrativo queiram sair dessas unidades. Agora, o que tem que ser feito é ter um código de vaga para aquela unidade antes da saída. para poder fazer o concurso."
+ },
+ {
+ "id_global": 305,
+ "fonte": "5o_debate",
+ "id_local": 20,
+ "timecode": "01:39:02",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesPorque, se não tiver esse cuidado, daqui a pouco nós vamos ter um êxito total, dos municípios fora de sede. Eu não estou generalizando, porque tem muita gente que gostou da cidade, quer permanecer, tanto Petrópolis, Friburgo, Angra dos Reis, Pádua. Então, todos os municípios onde a UFF está localizada, Volta Retonda, Campo. Então, a questão é justamente."
+ },
+ {
+ "id_global": 306,
+ "fonte": "5o_debate",
+ "id_local": 21,
+ "timecode": "01:39:34",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallestentar incentivar o professor a ficar melhorando a infraestrutura, o técnico administrativo também. Agora, a saída de um ou outro é natural, como também muita gente localizada nas unidades de Niterói querem transferência para outros locais. Então, é isso que nós temos que fazer. Nós temos que melhorar a estrutura para a fixação das pessoas, dando condições para que todos os municípios, Que todos possam exercer suas atividades docentes de técnico administrativo. Não sei se há..."
+ },
+ {
+ "id_global": 307,
+ "fonte": "5o_debate",
+ "id_local": 22,
+ "timecode": "01:40:05",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesTempo encerrado. Já está encerrado, mas na próxima você vai."
+ },
+ {
+ "id_global": 308,
+ "fonte": "5o_debate",
+ "id_local": 23,
+ "timecode": "01:44:19",
+ "topicos": "ReUni/Infra",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesNa verdade, eu queria inicialmente falar, respondendo isso aí à pergunta, que as pessoas tentam minimizar a questão da expansão. A expansão foi grandiosa. A expansão gerou muitos códigos vagas, foram centenas de concursos, tanto para técnico quanto para docente. Então, quando eu fazia ajustes de banco de equivalentes, era uma quantidade imensa. Então, a expansão, nós temos muito orgulho de ter participado."
+ },
+ {
+ "id_global": 309,
+ "fonte": "5o_debate",
+ "id_local": 24,
+ "timecode": "01:44:53",
+ "topicos": "Geral",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallese levado a UFF para esses oito municípios. Agora... Desculpe, Silvio, especificamente, repete a pergunta, por favor. Pode repetir, Anine."
+ },
+ {
+ "id_global": 310,
+ "fonte": "5o_debate",
+ "id_local": 25,
+ "timecode": "01:45:16",
+ "topicos": "30h/Teletrabalho|Eleições/Processo",
+ "classe": "confortavel",
+ "escore": 5,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesBom, a questão da regulamentação das 30 horas, primeiro que foi prometido na eleição passada, entre o primeiro e o segundo turno, 30 horas. E nós já sabíamos que tinha uma ação do Ministério Público, sobre a questão e o reitor anterior respondeu, obviamente, que estava colocando o ponto biomédico. Então, já se sabia disso. Agora, a questão das 30 horas começou com a gestão do reitor Raimundo, permaneceu na gestão do Gilberto Pedro Antunes,"
+ },
+ {
+ "id_global": 311,
+ "fonte": "5o_debate",
+ "id_local": 26,
+ "timecode": "01:45:49",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto Sallesduas gestões do Cícero e a nossa. Isso aí já tem, se for somar, mais de 30 anos. Já tem até jurisprudência. E como eu falei anteriormente, No nosso caso, nós iríamos ao Supremo e vamos ao Supremo, porque nós temos que exercer autonomia universitária. Então, nós temos que ter em mente que o reitor, obviamente, ele tem que ter os instrumentos, os instrumentos que ele tem."
+ },
+ {
+ "id_global": 312,
+ "fonte": "5o_debate",
+ "id_local": 27,
+ "timecode": "01:46:19",
+ "topicos": "30h/Teletrabalho|EAD/Remoto|Eleições/Processo",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesEle tem advogado anual, mas ele tem um procurador nomeado por ele. Então, nós vamos resgatar essa questão das 30 horas. Vamos estudar com a comunidade interessada, são os técnicos administrativos, sobre essa questão de como nós vamos trabalhar logo após a eleição, sem nenhuma... falar francamente o que está acontecendo. E agora, com a questão do teletrabalho."
+ },
+ {
+ "id_global": 313,
+ "fonte": "5o_debate",
+ "id_local": 28,
+ "timecode": "01:46:52",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesCom a pandemia, obviamente, as pessoas têm que procurar ficar mais com suas famílias, o transporte precário, E nós temos que valorizar uma riqueza que nós temos, que são nossos servidores. Então, nós não podemos abrir mão disso. Nós precisamos que todos voltem a sorrir. E não tenha mais essa dicotomia entre técnico, administrativo e professor. Então, nós vamos fazer o que nós sempre fizemos. Nós mantivemos as 30 horas dos 8 anos do mandato."
+ },
+ {
+ "id_global": 314,
+ "fonte": "5o_debate",
+ "id_local": 29,
+ "timecode": "01:55:10",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesEu vou perguntar para a chapa 1, aproveitando até o que o reitor falou e respeitando, obviamente, que o reitor, eu sei que ele está enfermo hoje e espero que ele se recupere rápido. O reitor falou que assinou 25 portarias sobre a concessão de liberação das 30 horas. Essas 25 portarias atingem quantos funcionários dos aproximadamente 4 mil técnicos administrativos?"
+ },
+ {
+ "id_global": 315,
+ "fonte": "5o_debate",
+ "id_local": 30,
+ "timecode": "01:59:13",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesA questão que eu perguntei realmente, que eu não sabia, não tenho esses números, não tenho acesso a isso, mas eu fiz um cálculo rápido aqui, se eu contar que são 4 mil servidores, então nós vamos ter um percentual, 150 representa em torno de 3% dos servidores, então o que eu estou entendendo é que a adesão está pequena, até talvez o que falte é esclarecimento à comunidade, não só dos pontos positivos, também dos pontos negativos,"
+ },
+ {
+ "id_global": 316,
+ "fonte": "5o_debate",
+ "id_local": 31,
+ "timecode": "01:59:51",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Salleseu acho que a comunidade não se sente esclarecida o suficiente no momento. Do meu ponto de vista, sobre... Quais são as vantagens e desvantagens? Algumas desvantagens nós já falamos aqui e não vamos repetir, que os servidores têm que, técnico administrativo, têm que saber disso. Talvez também seja por causa da insegurança jurídica sobre essa questão, já que o tempo que está colocado ali."
+ },
+ {
+ "id_global": 317,
+ "fonte": "5o_debate",
+ "id_local": 32,
+ "timecode": "02:00:26",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesna instituição normativa, mesmo que você não considere que seja tempo de experiência, mas são seis meses. Então, eu acho que durante esse tempo, que já vem se falando isso, já que a instituição normativa do ministro Paulo Guedes é de 2020, vocês implantaram uma instituição normativa agora, mas já tivemos um tempo suficiente, de repente, eu acho que falta esclarecimento, que a adesão é muito pequena. Então, eu acho até que você poderia explicar o porquê dessa adesão pequena de 3%, como você falou."
+ },
+ {
+ "id_global": 318,
+ "fonte": "5o_debate",
+ "id_local": 33,
+ "timecode": "02:01:00",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesE eu, sinceramente, não sabia do número. Eu perguntei até por curiosidade. Mas eu volto a repetir. Eu estou fazendo perguntas tranquilas porque eu entendo já tive há pouco tempo também com a mesma situação e a pessoa fica meio prostrada mesmo. Então, é isso. No sentido todo, sinceramente, é educadamente falando, camaradamente falando. É isso."
+ },
+ {
+ "id_global": 319,
+ "fonte": "5o_debate",
+ "id_local": 34,
+ "timecode": "02:11:56",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesNa verdade, Ui, se existe uma dificuldade, Já de algum tempo, né, da interação, inclusive, entre as próprias unidades aqui da UFF localizada em Niterói, ainda mais no interior. Essa que é a grande verdade, né, às vezes compra-se equipamentos repetidos que poderia ter sido conversado com as pessoas e usar o mesmo equipamento, o laboratório, seja o que for."
+ },
+ {
+ "id_global": 320,
+ "fonte": "5o_debate",
+ "id_local": 35,
+ "timecode": "02:12:29",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesMas eu acho o seguinte, a UFF é muito forte na questão da extensão. Tanto é verdade que nós trabalhamos na comissão em Brasília para provar para o ministro Rocieli que a extensão era auditável e passou, o ministro Rocieli recebeu o documento e disse que ia colocar justamente como fazendo parte da grade..."
+ },
+ {
+ "id_global": 321,
+ "fonte": "5o_debate",
+ "id_local": 36,
+ "timecode": "02:13:00",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesFicou lá na graduação e, obviamente, isso vai ser muito importante. Eu acho que a UFF tem um trabalho muito grande que esse trabalho fora dos muros, ele pode integrar várias unidades. Não só aqui como em todos os municípios. Por exemplo, quando nós tivemos aquele, desastre lá em Friburgo, naquela época, já tem alguns anos, nossas equipes de extensão foram todas a campo para poder."
+ },
+ {
+ "id_global": 322,
+ "fonte": "5o_debate",
+ "id_local": 37,
+ "timecode": "02:13:30",
+ "topicos": "Transparência/Orçamento",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallestrabalhar e trabalhar em conjunto, inclusive, com a comunidade lá da região. E o ministro na época era o Paim, foi muito sensível e liberou recursos para fazer a contenção não só da área da UFF, mas para proteger também a população local. Eu acho que é muito importante que a universidade possa ter essas redes e todos possam conhecer, inclusive, essa integração. Com a sociedade onde ela está ligada, porque é a sociedade, no final das contas, que vai defender a nossa universidade dos ataques que já vem sofrendo há algum tempo, em especial desse governo que está aí e tem restringido o orçamento das universidades."
+ },
+ {
+ "id_global": 323,
+ "fonte": "5o_debate",
+ "id_local": 38,
+ "timecode": "02:14:20",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesMas a UFF realmente tem esse potencial, ela pode fazer essa integração geral, não só aqui entre as unidades de Itarói, como também do interior e se relacionar com a sociedade. Mas nenhum reitor pode ter um prefeito preferido, ele tem que se relacionar com todos os prefeitos e usar a oportunidade que temos da UFF levar desenvolvimento econômico e social."
+ },
+ {
+ "id_global": 324,
+ "fonte": "5o_debate",
+ "id_local": 39,
+ "timecode": "02:17:18",
+ "topicos": "ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesEssa interação realmente é muito importante, até para aproximar nossas unidades nos municípios, onde a UFF cresceu muito com a ReUni, que muito nos orgulha, e aproximar justamente das unidades que já têm um certo tempo aqui, uma experiência na sede em Niterói, no município de Niterói. Acho isso fundamental. Agora, você lembrou muito bem da educação do campus, que nós incentivamos lá em Pádua."
+ },
+ {
+ "id_global": 325,
+ "fonte": "5o_debate",
+ "id_local": 40,
+ "timecode": "02:17:50",
+ "topicos": "Acessibilidade|Cultura/Cinema",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesRealmente foi muito importante e é importante. Nós temos que realmente incentivar esse tipo de curso de educação. Então, para justamente, não deixa de ser também uma inclusão muito grande, né, essa relação da universidade com as pessoas que têm essa tradição, né, na parte do campo, da agricultura, da pecuária, é fundamental. Então, e também a educação formal, né, terminou? A educação formal também."
+ },
+ {
+ "id_global": 326,
+ "fonte": "5o_debate",
+ "id_local": 41,
+ "timecode": "02:38:45",
+ "topicos": "Eleições/Processo",
+ "classe": "incomodado",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesSáline, um minuto de Trep, por favor. Eu acho até que a proposta do professor Fábio, eu queria responder que eu e Isabel já assinamos um documento, já está assinado previamente, mas eu gostaria de dizer muito bem... Que na eleição passada, que não era o governo golpista de agora, mas era um outro governo golpista da Dilma, não um outro golpista das eleições, em que o jornal O Globo, desde lá."
+ },
+ {
+ "id_global": 327,
+ "fonte": "5o_debate",
+ "id_local": 42,
+ "timecode": "02:39:15",
+ "topicos": "Eleições/Processo|ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallesatrás, era contra o Reúne, contra o governo Lula, depois ajudou no golpe, agora, colocou esse presidente que está aí, esse jornal O Globo, e os associados, que a gente sabe. Então, no governo Temer, já não foi assim, já não tinha nenhum, ele não nomeou ninguém nos governos anteriores que não fosse primeiro da lista. Então, com esse governo aí, realmente é impossível pensar. As regras, antigamente, eram essas. Os três mais votados entravam na lista."
+ },
+ {
+ "id_global": 328,
+ "fonte": "5o_debate",
+ "id_local": 43,
+ "timecode": "02:39:46",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallese o presidente sempre escolhia o primeiro lugar. Mas até o governo Temer, até o governo golpista do Temer. Mas depois disso, isso já não fizemos antes. Então, agora, Mas nós já assinamos, professor Fábio, fique tranquilo. Obrigado."
+ },
+ {
+ "id_global": 329,
+ "fonte": "5o_debate",
+ "id_local": 44,
+ "timecode": "02:47:17",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallesagradecer a você, Silvio, Aline, as duas tradutoras, aos candidatos aqui presentes, a todos que nos estão assistindo. Eu, a professora Isabel, chapa 3, UFF Plural Democrática, mas eu tenho que fazer algumas considerações que eu escutei. Eu escutei falar aqui que, o reitor foi condenado a colocar o ponto eletrônico, mas eu não entendi. Colocou o ponto biomédico e a justiça também obrigou a 40 horas. Eu estou repetindo só o que foi."
+ },
+ {
+ "id_global": 330,
+ "fonte": "5o_debate",
+ "id_local": 45,
+ "timecode": "02:47:48",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesfalado. Agora, o que tem que ser falado é que esse processo, realmente nós temos que ter uma maneira de nos, relacionar depois de pandemia. Com as pessoas com tranquilidade. Mas esse processo que atinge até agora só 3%, 150 servidores, ele passa o ônus não só para o servidor em termos de custo, como também passa para os chefes do departamento e diretores para fazer toda a tarefa."
+ },
+ {
+ "id_global": 331,
+ "fonte": "5o_debate",
+ "id_local": 46,
+ "timecode": "02:48:19",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesA reitoria itinerante começou com o professor Pedro Antunes e nós fizemos isso para nos aproximar das unidades fora de sede. E nós vamos continuar. Fizemos isso durante oito anos, porque isso dá uma sensação de pertencimento. Isso é muito importante. Agora, na nossa época, a pró-reitoria de extensão tinha cadastrado mais de 500 projetos, mais de 500, em toda a UFF, onde ela estivesse presente."
+ },
+ {
+ "id_global": 332,
+ "fonte": "5o_debate",
+ "id_local": 47,
+ "timecode": "02:48:52",
+ "topicos": "Eleições/Processo",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesVou dar um exemplo do SCOS UFF Comunidade. Um projeto realmente que nós ajudávamos a comunidade, inclusive em caso de desastre. Então, eu convoco a todos também para votarem. Chapa 3. Nós estamos atentos. Esperamos, viu, Reitor, que a eleição não seja igual à passada. Realmente, esperamos que seja, tranquilo, correta, que não tenhamos pessoas cedidas a outro órgão, que a Bicera é um outro órgão, votando,"
+ },
+ {
+ "id_global": 333,
+ "fonte": "5o_debate",
+ "id_local": 48,
+ "timecode": "02:49:23",
+ "topicos": "Eleições/Processo",
+ "classe": "incomodado",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto Sallesprofessor aposentado votando. Então, isso aí é urna na sala de diretor. Esperamos que não aconteça nada disso. Então, se não acontecer nada disso, está tudo ok. Mas ninguém pretende fazer nada. Nós também, mais do que ninguém, queremos lisura total, professor Isabel."
+ },
+ {
+ "id_global": 334,
+ "fonte": "6o_debate_P1",
+ "id_local": 1,
+ "timecode": "00:24:25",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesMeu nome é Roberto Salles, eu entrei na universidade em 1977 como estudante, recebi uma bolsa social, era a única bolsa existente na época, bolsa de trabalho, além da monitoria e bolsa de extensão. Tive a oportunidade de chegar a reitor em 2006, dentro do governo Lula. Eu quero já deixar claro para todos que nós temos a educação comum."
+ },
+ {
+ "id_global": 335,
+ "fonte": "6o_debate_P1",
+ "id_local": 2,
+ "timecode": "00:25:00",
+ "topicos": "Governança/PDI|ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesO investimento, não como despesa, é absurdo, mais uma tentativa de cobrança de mensalidades. Nós acreditamos no projeto do governo Lula e fizemos o maior projeto de reestruturação e expansão. Foram 380 milhões de reais. Agora, por que deu certo? Porque colocamos o projeto no PDI, no Plano de Desenvolvimento Institucional. Todos puderam ir lá discutir e apresentar sua proposta, a sua ideia."
+ },
+ {
+ "id_global": 336,
+ "fonte": "6o_debate_P1",
+ "id_local": 3,
+ "timecode": "00:25:33",
+ "topicos": "Transparência/Orçamento",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesÉ como se fosse um orçamento participativo. Então, esse recurso foi extremamente vigiado, foi extremamente acompanhado e o recurso não andava para um ano e para o outro. Ele tinha que ser usado naquele ano. Então, conseguimos dobrar praticamente o tamanho da universidade, construir a moradia aqui em Rio das Ostras, que era uma reivindicação de 50%. Conseguimos comprar todos os ônibus. Os membros do BUSUFF são daquela época de 10, 12, 11 anos."
+ },
+ {
+ "id_global": 337,
+ "fonte": "6o_debate_P1",
+ "id_local": 4,
+ "timecode": "00:26:05",
+ "topicos": "Acessibilidade",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesConseguimos também fazer a maior inclusão do país. Nós incluímos a universidade dentro do projeto apresentado no governo Lula, das bolsas. A lei de cotas nós implantamos em dois anos, quando a lei falava quatro anos. Foram 10.500 pessoas entrando por ano em 2014. 13 modalidades de bolsas. Agora, nós temos que avançar."
+ },
+ {
+ "id_global": 338,
+ "fonte": "6o_debate_P1",
+ "id_local": 5,
+ "timecode": "00:26:36",
+ "topicos": "Hospital/EBSERH",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesDobramos o tamanho do bandejão aqui no Graguatá, abrimos da Praia Vermelha, abrimos da Reitoria e do Hospital e reformamos a veterinária. Agora, precisamos avançar. Realmente, nós tivemos uma pandemia que seifou muitas vidas, lamentável. A UFF desses dois anos fez uma economia, agora devia ter se preparado. Obrigado."
+ },
+ {
+ "id_global": 339,
+ "fonte": "6o_debate_P1",
+ "id_local": 6,
+ "timecode": "01:01:36",
+ "topicos": "Acessibilidade",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesBom, nós criamos o setor de acessibilidade e inclusão. Essa pavimentação toda aqui do campo de Graguatá foi em parceria com a prefeitura, inclusive acessibilidade tática. Agora, o que se esperava é que nesses anos pudesse progredir a questão da acessibilidade. Inclusive com pessoas com deficiências, a partir da exigência da lei. O tempo está errado."
+ },
+ {
+ "id_global": 340,
+ "fonte": "6o_debate_P1",
+ "id_local": 7,
+ "timecode": "01:10:31",
+ "topicos": "Geral",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesEu queria lembrar que, na verdade, o caminho para a negociação com os BRICS foi na nossa gestão. Pode ter sido assinado um acordo depois, mas foi na nossa gestão. Isso aí não pode ser esquecido. Também abraçamos a causa dos ciências... A fronteira no governo Lula, né?"
+ },
+ {
+ "id_global": 341,
+ "fonte": "6o_debate_P1",
+ "id_local": 8,
+ "timecode": "01:11:02",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesVários estudantes, graduação e pós-graduação, tiveram a oportunidade de ir para o exterior. Às vezes foi a única viagem que a pessoa fez na vida. Isso foi importante. Trouxemos também o Instituto Confúcio para o ensino do mandarim. Apoiamos o PROLEM em vários, num crescimento muito grande em língua estrangeira. Não só o mandarim, o alemão e várias outras línguas. Então, nós não podemos esquecer que a universidade realmente deu um salto muito grande."
+ },
+ {
+ "id_global": 342,
+ "fonte": "6o_debate_P1",
+ "id_local": 9,
+ "timecode": "01:11:38",
+ "topicos": "EAD/Remoto",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesLevamos a universidade aberta para a África, para treinar a universidade, para treinar o pessoal lá."
+ },
+ {
+ "id_global": 343,
+ "fonte": "6o_debate_P1",
+ "id_local": 10,
+ "timecode": "01:12:34",
+ "topicos": "Transparência/Orçamento",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesChapa 2, gostaria de, na sua visão, sendo a nossa universidade muito forte em extensão, inclusive na comissão que nós tivemos em Brasília, na Câmara de Deputados. Então, colocamos a extensão, provamos que a extensão era auditável e agora faz parte obrigatória da grade curricular na graduação e vai fazer parte da matriz."
+ },
+ {
+ "id_global": 344,
+ "fonte": "6o_debate_P1",
+ "id_local": 11,
+ "timecode": "01:13:13",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEntão, eu gostaria de perguntar qual é a sua visão dessa política de integração entre a universidade e a sociedade com essa visão forte de extensionista da UFF."
+ },
+ {
+ "id_global": 345,
+ "fonte": "6o_debate_P1",
+ "id_local": 12,
+ "timecode": "01:17:00",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesA extensão da UFF já foi o exemplo. Tivemos recentemente um fórum de pró-reitores de extensão da região Sudeste, foi sediada pelo UFRJ. E a UFF nem participou de nenhuma mesa para ver a importância que estão dando a extensão dentro da universidade."
+ },
+ {
+ "id_global": 346,
+ "fonte": "6o_debate_P1",
+ "id_local": 13,
+ "timecode": "01:17:33",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEu lembro muito bem que nós fizemos um convênio com a Fábio para levar os nossos estudantes professores em projetos sem nenhum custo para oriximinar. Isso perdurou durante muito tempo e foi muito importante para os estudos, vários estudos naquela região. Então, o que nós temos de fazer é resgatar... A nossa extensão da nossa Universidade Federal Fluminense, ainda mais agora, que faz parte da grade curricular."
+ },
+ {
+ "id_global": 347,
+ "fonte": "6o_debate_P1",
+ "id_local": 14,
+ "timecode": "01:18:08",
+ "topicos": "Transparência/Orçamento",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesIsso vai representar recurso na matriz orçamentária. Não é possível, eu lembro também das tragédias que nós tivemos em Friburgo, em Petrópolis, que a UFF participou ativamente com o SOS UFF, com várias equipes indo lá ajudando. Esse é o papel da Universidade. É assim que a Universidade se mostra para a sociedade, através da extensão. Saindo dos seus muros e indo à comunidade. Isso é bom para o ensino, para a pesquisa, para a pós-graduação, é bom para todo mundo."
+ },
+ {
+ "id_global": 348,
+ "fonte": "6o_debate_P1",
+ "id_local": 15,
+ "timecode": "01:18:43",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesE, obviamente, que aproxima a sociedade que defende a Universidade. Então, é fundamental resgatar a extensão da Universidade Federal Fluminense."
+ },
+ {
+ "id_global": 349,
+ "fonte": "6o_debate_P1",
+ "id_local": 16,
+ "timecode": "01:22:50",
+ "topicos": "30h/Teletrabalho|Eleições/Processo",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesSe estabeleceu uma dicotomia, uma guerra entre docentes e técnico administrativo desnecessário. Por causa da questão do programa de gestão e desempenho que contempla o teletrabalho. Na verdade, o que deveria ter sido, e pior, que é perto da eleição, né? Eu lembro que já foi colocado anteriormente, na eleição passada, que era a promessa das 30 horas, era radicalmente favorável."
+ },
+ {
+ "id_global": 350,
+ "fonte": "6o_debate_P1",
+ "id_local": 17,
+ "timecode": "01:23:21",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesE o que aconteceu? Não aconteceu as 30 horas, aconteceu 45 horas com ponto biométrico, né? E agora, uma instrução normativa do Guedes, 2020, sendo implantada agora em 2022, não é? E o que poderia ter sido feito? Discutir com a comunidade, com os interessados, os técnicos administrativos, ainda mais depois de uma pandemia, qual é a melhor forma de cumprir sua carga horária, não é?"
+ },
+ {
+ "id_global": 351,
+ "fonte": "6o_debate_P1",
+ "id_local": 18,
+ "timecode": "01:23:53",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesE é isso que nós iríamos fazer e vamos fazer, é conversar com a categoria. Sobre... Por exemplo, no debate passado, eu perguntei quantas portarias tinham sido assinadas. 25. Qual o público alcançado? 150 técnicos administrativos em 4 mil. Isso não resolve o problema. Então, o que nós precisamos fazer é discutir essa questão, como aplicar as 30 horas e como cobrar a produtividade em vez do tempo que a pessoa fica na universidade. Nós estamos na contramão do mundo."
+ },
+ {
+ "id_global": 352,
+ "fonte": "6o_debate_P1",
+ "id_local": 19,
+ "timecode": "01:24:34",
+ "topicos": "Geral",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesNós temos a Europa, um sistema de transporte eficiente. Aqui a pessoa demora duas horas para ir e voltar, não convive direito com sua família, ainda tem que ficar nessa tensão. O que fazer? E além do mais, atribui, passa para o técnico uma série de atribuições, como ele ficar em casa. E ter todas as despesas da parte de ergometria, energia e podendo perder realmente alguns direitos, como o vale-transporte."
+ },
+ {
+ "id_global": 353,
+ "fonte": "6o_debate_P1",
+ "id_local": 20,
+ "timecode": "01:25:09",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesEu acho que essa discussão tem que ser recomeçar, trazer a paz dentro da universidade e uma relação sincera com os técnicos administrativos. E que todos possam trabalhar sorridentes e felizes dentro da Universidade Federal Fluminense."
+ },
+ {
+ "id_global": 354,
+ "fonte": "6o_debate_P1",
+ "id_local": 21,
+ "timecode": "01:28:04",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesBom, nós vamos também, houve uma pequena confusão entre ponto biométrico e ponto eletrônico. Não havia necessidade de se colocar o ponto biométrico. Nós também vamos acabar com o ponto biométrico e vamos rediscutir toda essa questão com o segmento mais interessado, que é o técnico administrativo para essa questão. A outra questão também é que essa modalidade não atinge todos os servidores da universidade."
+ },
+ {
+ "id_global": 355,
+ "fonte": "6o_debate_P1",
+ "id_local": 22,
+ "timecode": "01:28:43",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEntão vai depender de uma série de fatores, vai depender inclusive da chefia, de aplicar, quer dizer, também transfere uma série de trabalhos para as chefias. Então realmente está muito confuso, isso tem que ser explicado. Com clareza, para que as pessoas possam optar ou não pelo que querem fazer em relação ao seu trabalho. Não dá para ficar nessa confusão e causar esse pânico dentro da Universidade Federal Fluminense."
+ },
+ {
+ "id_global": 356,
+ "fonte": "6o_debate_P2",
+ "id_local": 1,
+ "timecode": "00:08:19",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesObrigado, decano do Conselho, professor Palharini. Palharini, nós tivemos uma comissão em Brasília presidindo 3 rejeitores e foi nossa comissão que sepultou o Futuris. Dizemos tanto na comissão de educação da Câmara do Senado, dissemos não o Futuris e falamos que o Futuris não tinha futuro. A outra questão é que foi falado aqui, que já está aprovado que a cobrança de mensalidade não cobre 20% de toda a despesa que a universidade tem."
+ },
+ {
+ "id_global": 357,
+ "fonte": "6o_debate_P2",
+ "id_local": 2,
+ "timecode": "00:08:52",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesEntão a educação tem que ser carada como investimento, não como despesa. E a outra coisa também... Quem vai ser o presidente do Brasil é Lula, e nós seremos reitor na gestão de Lula. É isso, não tem outra opção para o bem da educação, da saúde, do meio ambiente e do social. E nós vamos fazer outro projeto na gestão do Lula e José Henrique Paim, ministro da Educação. Então é isso."
+ },
+ {
+ "id_global": 358,
+ "fonte": "6o_debate_P2",
+ "id_local": 3,
+ "timecode": "00:19:09",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesBom, pelo que nós pudemos observar do programa de gestão e desempenho que contempla o teletrabalho, é realmente muito sofisticado. As pessoas têm várias modalidades, inclusive o teletrabalho temporário, mas aqui em nenhum momento isenta claramente de bater o ponto, inclusive o ponto biométrico,"
+ },
+ {
+ "id_global": 359,
+ "fonte": "6o_debate_P2",
+ "id_local": 4,
+ "timecode": "00:19:41",
+ "topicos": "30h/Teletrabalho",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallesnão está claro, porque nem todo mundo vai poder aderir, vai ter um período de seis meses para poder avaliar que tudo pode acontecer e vai ter um edital, né? E dependendo do edital, se tiver mais de um... O candidato para essa vaga, obviamente, uma pessoa vai ficar de fora, né? Então, não isenta, não está claro dessa isenção de bater o ponto, em especial o ponto biométrico."
+ },
+ {
+ "id_global": 360,
+ "fonte": "6o_debate_P2",
+ "id_local": 5,
+ "timecode": "00:20:15",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesMas nós, eu e a professora Isabel, vamos claramente abolir o ponto biométrico. Vamos rediscutir a questão desse trabalho do Programa de Gestão e Desempenho. Vamos discutir com a categoria, não é? E vamos também discutir e ir ao Supremo pelas 30 horas. Isso aí é uma decisão que nós tomamos e não vamos abrir mão dessa decisão nossa."
+ },
+ {
+ "id_global": 361,
+ "fonte": "6o_debate_P2",
+ "id_local": 6,
+ "timecode": "00:20:48",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesAgora, esse Programa de Gestão e Desempenho, ele tem que ser discutido melhor com a comunidade. Tem pessoas que conhecem profundamente. O setor sabe como trabalhar com isso. Então, nem todos podem aderir. Essa que é a questão, dependendo do local que se trabalha. E também, o servidor deverá preencher o VELT."
+ },
+ {
+ "id_global": 362,
+ "fonte": "6o_debate_P2",
+ "id_local": 7,
+ "timecode": "00:21:23",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesE tem um código ainda, são três códigos para o funcionário escolher. Se ele vai trabalhar parcialmente. Tem um código que é participante do teletrabalho total. Tem um código que é para o teletrabalho de teletrabalho. Tem outro, o código 400 para os participantes do teletrabalho parcial. 401 para os participantes do modelo presencial."
+ },
+ {
+ "id_global": 363,
+ "fonte": "6o_debate_P2",
+ "id_local": 8,
+ "timecode": "00:21:57",
+ "topicos": "30h/Teletrabalho",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesEntão, veja bem a confusão. se instalou com essa questão desse plano. Então, por isso tem que ser discutido e nós vamos discutir. Agora, vamos abolir imediatamente o ponto biométrico. Isso aí não tem nenhuma dúvida."
+ },
+ {
+ "id_global": 364,
+ "fonte": "6o_debate_P2",
+ "id_local": 9,
+ "timecode": "00:40:04",
+ "topicos": "Acessibilidade",
+ "classe": "confortavel",
+ "escore": 1,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesCom a inclusão que a UFF fez no governo Lula, a grande inclusão, nós temos que abrir a caixa do recurso do PNAES. Recurso do PNAES, a UFF é que recebe maior quantidade de recurso do PNAES, mesmo com os cortes. E o dinheiro para ser usado obedece alguns itens importantes."
+ },
+ {
+ "id_global": 365,
+ "fonte": "6o_debate_P2",
+ "id_local": 10,
+ "timecode": "00:40:36",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEsses itens têm que ser seguidos, por exemplo, não pode pagar vigilância e limpeza com dinheiro PNAES. Dinheiro PNAES é para assistência estudantil. E a UFF, a UFF está inserida em oito municípios. O Estado é rico em royalties de petróleo. Nada mais justo do que fazer parcerias com esses municípios para abrir... bandejões e moradias. Também é importante a UFF criar um fundo junto com esses municípios,"
+ },
+ {
+ "id_global": 366,
+ "fonte": "6o_debate_P2",
+ "id_local": 11,
+ "timecode": "00:41:08",
+ "topicos": "Acessibilidade",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto Sallesjá que o Estado é rico em roda de petróleo, para poder ajudar na assistência estudantil e na inclusão. Essas são as propostas concretas. Primeiro é saber quanto nós estamos recebendo do PNAJ. A Universidade Federal Fluminense é uma das que mais recebe. Levando em consideração os cortes. A quantidade de recursos é grande. Isso tem que ser discutido com os estudantes, que são os maiores interessados. E é isso que nós vamos fazer."
+ },
+ {
+ "id_global": 367,
+ "fonte": "6o_debate_P2",
+ "id_local": 12,
+ "timecode": "00:54:48",
+ "topicos": "30h/Teletrabalho",
+ "classe": "incomodado",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesBom, eu estou vendo aqui, apesar do reitor dizer que não vai ser, obrigatório... Bater o ponto, tem dito que isso que não vai ser, não terá mais ponto biométrico. Mas olha o que diz aqui a Progep, diz ser necessário o cadastro da biometria daqueles que ainda não possuem, pois será preciso para utilização do ponto biométrico a partir."
+ },
+ {
+ "id_global": 368,
+ "fonte": "6o_debate_P2",
+ "id_local": 13,
+ "timecode": "00:55:26",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto Sallesde 1º de julho. Então, como eu falei anteriormente, está muito realmente confusa essa discussão. Eu acho que precisaria de mais tempo para poder discutir com os maiores interessados que são os técnicos administrativos, porque o que está escrito aqui é uma coisa, da instrução normativa de 2022, mas que segue uma instrução normativa do Guedes de 2020. Então, acho que tem que ter mais clareza para as pessoas."
+ },
+ {
+ "id_global": 369,
+ "fonte": "6o_debate_P2",
+ "id_local": 14,
+ "timecode": "00:55:59",
+ "topicos": "Geral",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesPois sabe. Eu estou lendo exatamente o que está escrito na instrução normativa daqueles que não vão aderir. E fora a confusão que tem dos que vão aderir, falta de esclarecimento em relação às modalidades e também a questão dos códigos que tem que ser usado para o VELT. Então, eu inverto a pergunta e gostaria que o reitor esclarecesse melhor essa questão, que todo mundo está confuso. Até eu me sinto confuso a partir do momento em que eu leio o que está exposto aqui, colocado pela própria Pró-Reitoria de Gestão de Pessoas."
+ },
+ {
+ "id_global": 370,
+ "fonte": "6o_debate_P2",
+ "id_local": 15,
+ "timecode": "00:56:47",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesEntão, eu fico realmente muito confuso em relação ao que realmente vai acontecer. E quero lembrar também que... Essa instrução normativa é por seis meses, ela pode ser revogada a qualquer momento. E tem a outra questão, se o servidor for desligado por algum motivo, ele espera um ano para entrar novamente. Então, realmente, reitor, pode explicar para a gente, porque está bem confuso."
+ },
+ {
+ "id_global": 371,
+ "fonte": "6o_debate_P2",
+ "id_local": 16,
+ "timecode": "00:59:56",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesReitor, infelizmente não está tão claro assim como você está falando. Por que não está tão claro? Você mesmo respondeu no último debate que você assinou 25 portarias com adesão de 150 técnicos administrativos em 4 mil. Se tivesse realmente bem claro, nós teríamos pelo menos 2 mil técnicos administrativos aderindo. Então, isso mostra que não está claro."
+ },
+ {
+ "id_global": 372,
+ "fonte": "6o_debate_P2",
+ "id_local": 17,
+ "timecode": "01:00:28",
+ "topicos": "Geral",
+ "classe": "incomodado",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesPrecisa de clareza para as pessoas entenderem o que vão assinar ou não assinar. Então, está aqui claramente, você falou isso. 150 técnicos representa 3% de 4 mil. Então, que clareza é essa? Eu não consigo entender."
+ },
+ {
+ "id_global": 373,
+ "fonte": "6o_debate_P2",
+ "id_local": 18,
+ "timecode": "01:25:25",
+ "topicos": "Morro do Gragoatá",
+ "classe": "incomodado",
+ "escore": 3,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesEu gostaria de perguntar à Chapa 2 sobre uma questão do horto florestal da universidade. Muita gente não conhece que tem um horto florestal, coordenado pela professora Jane, em que, quando você olha o retrato daquele morro, que tem um platô de 4 hectares, ele não tinha nenhuma vegetação. Com o esforço dos alunos, a professora Jane plantou uma mata tântrica e estava subindo ao morro. E o que aconteceu? De repente, veio uma empreiteira dizendo..."
+ },
+ {
+ "id_global": 374,
+ "fonte": "6o_debate_P2",
+ "id_local": 19,
+ "timecode": "01:26:00",
+ "topicos": "Morro do Gragoatá",
+ "classe": "confortavel",
+ "escore": 0,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesEntão, Roberto, esse é o caso conhecido como do Morro do Gragoatá."
+ },
+ {
+ "id_global": 375,
+ "fonte": "6o_debate_P2",
+ "id_local": 20,
+ "timecode": "01:29:42",
+ "topicos": "ReUni/Infra",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "média",
+ "trecho": "XXX_Roberto SallesO trabalho feito lá pela professora Jane é um trabalho muito importante para o ensino, pesquisa e extensão. E é um trabalho também bonito para a natureza. Eu já percorri lá quatro vezes. Fui até Laupatô, vendo que maravilha de mata. Imagina quatro hectares, 40 mil metros quadrados do platô, a quantidade de floresta que pode crescer ali em harmonia com aquele ambiente."
+ },
+ {
+ "id_global": 376,
+ "fonte": "6o_debate_P2",
+ "id_local": 21,
+ "timecode": "01:30:13",
+ "topicos": "Geral",
+ "classe": "neutro",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto SallesAgora, não é possível, não é aceitável que uma empreiteira, de vez em quando, ela faz isso. Ela vai e diz que é dona do pedaço. Só que tem uma decisão do Tribunal Federal Regional dizendo que a UFF é dona administrativa. Mas queriam provar para a gente, e gente da própria universidade, que tinha que indenizar aquela empresa. E aí o que aconteceu? Acionamos o Ministério Público, um conjunto de pessoas, e o Ministério Público contestou o juiz,"
+ },
+ {
+ "id_global": 377,
+ "fonte": "6o_debate_P2",
+ "id_local": 22,
+ "timecode": "01:30:45",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallese o desembargador da turma da segunda região simplesmente foi e deu uma chamada de juiz dizendo não estou entendendo sua decisão. Essa área aqui pertence à Universidade Federal Fluminense. Então nós não podemos... ...desperdiçar um espaço tão importante, já que nós estamos falando em sustentabilidade, e termos uma mata atlântica daquela magnitude. Muita gente não conhece, deveria conhecer, ir lá, entra pela engenharia e vocês vão ver."
+ },
+ {
+ "id_global": 378,
+ "fonte": "6o_debate_P2",
+ "id_local": 23,
+ "timecode": "01:31:15",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallesque espaço maravilhoso, que espaço ambiental e que trabalho que foi feito ao longo dos anos. E esse trabalho nós não vamos abrir a mão, vamos defender a todo custo. A UFF é dona administrativa."
+ },
+ {
+ "id_global": 379,
+ "fonte": "6o_debate_P2",
+ "id_local": 24,
+ "timecode": "01:37:36",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 6,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesBom, Guilherme, eu gostaria de agradecer em primeiro lugar a presidência da mesa, junto com a professora que está auxiliando, a professora Alissandra, a professora Flávia, aos candidatos, o Wilson, o Vladimir, Antônio, Cláudio, o Fábio, a vocês todos presentes aqui, a vocês que estão presentes nos assistindo, a equipe da UFF. Na pessoa do Gilson, queria dar os parabéns pelo trabalho e dizer que nós chegamos ao final tranquilos, nós mostramos tudo o que nós fizemos e que podemos fazer, temos a experiência, conhecemos bastante a universidade, estamos há 45 anos dentro dessa universidade, só não participei da gestão de quatro reitores dentro dessa universidade em 62 anos."
+ },
+ {
+ "id_global": 380,
+ "fonte": "6o_debate_P2",
+ "id_local": 25,
+ "timecode": "01:38:30",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 3,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesEntão eu sou muito grato à Universidade Federal Fluminense por tudo que me proporcionou, as pessoas que trabalham e estudam na universidade, foi um aprendizado muito grande ao longo de todos esses anos, então nós nos sentimos à vontade para pedir o voto na chapa 3, UFF e Plural Democrática, que todos possam entrar no nosso Facebook, Instagram, analisar nossas... As propostas são muito claras, objetivas e precisamos do apoio de toda a comunidade,"
+ },
+ {
+ "id_global": 381,
+ "fonte": "6o_debate_P2",
+ "id_local": 26,
+ "timecode": "01:39:07",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 2,
+ "confianca": "baixa",
+ "trecho": "XXX_Roberto Sallesnão só dos estudantes, dos professores, dos técnicos administrativos. A nossa chapa precisa do voto dos três segmentos, não elegemos um segmento como especial. Todos os três segmentos são especiais. E vamos manter como mantivemos os oito anos, de uma relação próxima a cada unidade. O lugar que nós vamos parar menos é no gabinete do reitor. Nós vamos circular a universidade, não só aqui onde ela estiver presente, nos oito municípios."
+ },
+ {
+ "id_global": 382,
+ "fonte": "6o_debate_P2",
+ "id_local": 27,
+ "timecode": "01:39:42",
+ "topicos": "Geral",
+ "classe": "confortavel",
+ "escore": 4,
+ "confianca": "alta",
+ "trecho": "XXX_Roberto SallesO diálogo com os órgãos de classe, adultos, cinturos, DCE, será o que nós fizemos anteriormente. Então, peço voto para a chapa 3, Rufo Plural Democrático. Muito obrigado."
+ }
+]
\ No newline at end of file
diff --git a/data_ingestion.py b/data_ingestion.py
new file mode 100644
index 0000000..232df44
--- /dev/null
+++ b/data_ingestion.py
@@ -0,0 +1,299 @@
+"""
+Módulo para ingestão flexível de dados de múltiplas fontes.
+Suporta JSON, CSV, TXT, PDF e outros formatos.
+"""
+
+import json
+import csv
+from pathlib import Path
+from typing import List, Dict, Any, Optional
+from datetime import datetime
+import hashlib
+
+
+class DataIngestion:
+ """Gerenciador de ingestão de dados flexível."""
+
+ def __init__(self, data_dir: str = "data"):
+ self.data_dir = Path(data_dir)
+ self.temp_dir = self.data_dir / "temp_uploads"
+ self.temp_dir.mkdir(exist_ok=True)
+
+ def generate_doc_id(self, content: str, source: str) -> str:
+ """Gera ID único baseado no conteúdo."""
+ hash_content = hashlib.md5(f"{source}_{content}".encode()).hexdigest()
+ return f"custom_{hash_content[:16]}"
+
+ def ingest_json(
+ self,
+ file_path: Path,
+ profile_name: str = "custom_data",
+ content_type: str = "custom_ingestion" # 🆕 NOVO PARÂMETRO
+ ) -> List[Dict[str, Any]]:
+ """
+ Ingere arquivo JSON.
+
+ Aceita tanto formato de posts do Instagram quanto JSON genérico.
+ """
+ with open(file_path, 'r', encoding='utf-8') as f:
+ data = json.load(f)
+
+ # Se for lista, processa cada item
+ if isinstance(data, list):
+ return [self._normalize_document(item, profile_name, i, content_type)
+ for i, item in enumerate(data)]
+
+ # Se for dict único, processa como documento único
+ return [self._normalize_document(data, profile_name, 0, content_type)]
+
+ def ingest_csv(
+ self,
+ file_path: Path,
+ profile_name: str = "custom_data",
+ content_type: str = "custom_ingestion", # 🆕 NOVO PARÂMETRO
+ text_column: str = "text",
+ title_column: Optional[str] = None,
+ date_column: Optional[str] = None
+ ) -> List[Dict[str, Any]]:
+ """
+ Ingere arquivo CSV.
+
+ Args:
+ file_path: Caminho do CSV
+ profile_name: Nome do perfil/fonte
+ content_type: Tipo de conteúdo customizado
+ text_column: Nome da coluna com texto principal
+ title_column: Nome da coluna com título (opcional)
+ date_column: Nome da coluna com data (opcional)
+ """
+ documents = []
+
+ with open(file_path, 'r', encoding='utf-8') as f:
+ reader = csv.DictReader(f)
+
+ for i, row in enumerate(reader):
+ if text_column not in row:
+ raise ValueError(f"Coluna '{text_column}' não encontrada no CSV")
+
+ doc = {
+ 'text': row[text_column],
+ 'title': row.get(title_column, '') if title_column else f"Documento {i+1}",
+ 'metadata': {k: v for k, v in row.items() if k != text_column}
+ }
+
+ if date_column and date_column in row:
+ doc['date'] = row[date_column]
+
+ documents.append(self._normalize_document(doc, profile_name, i, content_type))
+
+ return documents
+
+ def ingest_text(
+ self,
+ file_path: Path,
+ profile_name: str = "custom_data",
+ content_type: str = "custom_ingestion", # 🆕 NOVO PARÂMETRO
+ split_by: str = "\n\n"
+ ) -> List[Dict[str, Any]]:
+ """
+ Ingere arquivo de texto.
+
+ Args:
+ file_path: Caminho do arquivo TXT
+ profile_name: Nome do perfil/fonte
+ content_type: Tipo de conteúdo customizado
+ split_by: Separador para dividir texto em documentos
+ """
+ with open(file_path, 'r', encoding='utf-8') as f:
+ content = f.read()
+
+ # Divide texto em documentos
+ chunks = [c.strip() for c in content.split(split_by) if c.strip()]
+
+ return [
+ self._normalize_document(
+ {'text': chunk, 'title': f"Trecho {i+1}"},
+ profile_name,
+ i,
+ content_type # 🆕 PASSA TIPO CUSTOMIZADO
+ )
+ for i, chunk in enumerate(chunks)
+ ]
+
+ def ingest_pdf(
+ self,
+ file_path: Path,
+ profile_name: str = "custom_data",
+ content_type: str = "custom_ingestion" # 🆕 NOVO PARÂMETRO
+ ) -> List[Dict[str, Any]]:
+ """
+ Ingere arquivo PDF.
+
+ Requer: pip install pypdf2
+ """
+ try:
+ from PyPDF2 import PdfReader
+ except ImportError:
+ raise ImportError("PyPDF2 não instalado. Execute: uv pip install pypdf2")
+
+ reader = PdfReader(str(file_path))
+ documents = []
+
+ for i, page in enumerate(reader.pages):
+ text = page.extract_text().strip()
+ if text:
+ documents.append(
+ self._normalize_document(
+ {'text': text, 'title': f"Página {i+1}"},
+ profile_name,
+ i,
+ content_type # 🆕 PASSA TIPO CUSTOMIZADO
+ )
+ )
+
+ return documents
+
+ def _normalize_document(
+ self,
+ doc: Dict[str, Any],
+ profile_name: str,
+ index: int,
+ content_type: str = "custom_ingestion" # 🆕 NOVO PARÂMETRO
+ ) -> Dict[str, Any]:
+ """
+ Normaliza documento para formato padrão do sistema.
+
+ Formato compatível com embedding_manager.py e data_loader.py
+
+ Args:
+ doc: Documento a ser normalizado
+ profile_name: Nome do perfil/fonte
+ index: Índice do documento
+ content_type: Tipo de conteúdo customizado
+ """
+ # Extrai texto principal
+ text = doc.get('text', '') or doc.get('content', '') or doc.get('caption', '')
+
+ if not text:
+ text = json.dumps(doc, ensure_ascii=False)
+
+ # Gera ID único
+ doc_id = self.generate_doc_id(text, profile_name)
+
+ # Cria timestamp
+ timestamp = datetime.now()
+ if 'date' in doc:
+ try:
+ from dateutil import parser as date_parser
+ timestamp = date_parser.parse(doc['date'])
+ except:
+ pass
+
+ # Formato normalizado (compatível com InstagramDataLoader)
+ normalized = {
+ 'id': doc.get('id', doc_id),
+ 'profile': profile_name,
+ 'content_type': content_type, # 🆕 USA O TIPO CUSTOMIZADO
+ 'type': doc.get('type', 'Document'),
+ 'text': text,
+ 'url': doc.get('url', ''),
+ 'title': doc.get('title', ''),
+ 'description': doc.get('description', ''),
+ 'timestamp': timestamp,
+ 'likesCount': doc.get('likesCount', 0),
+ 'commentsCount': doc.get('commentsCount', 0),
+ 'hashtags': doc.get('hashtags', []),
+ 'mentions': doc.get('mentions', []),
+ 'metadata': doc.get('metadata', {})
+ }
+
+ return normalized
+
+ def get_supported_formats(self) -> List[str]:
+ """Retorna formatos suportados."""
+ return ['.json', '.csv', '.txt', '.pdf']
+
+ def validate_file(self, file_path: Path) -> tuple[bool, str]:
+ """
+ Valida arquivo antes de processar.
+
+ Returns:
+ (is_valid, error_message)
+ """
+ if not file_path.exists():
+ return False, "Arquivo não encontrado"
+
+ if file_path.suffix.lower() not in self.get_supported_formats():
+ return False, f"Formato {file_path.suffix} não suportado"
+
+ if file_path.stat().st_size > 50 * 1024 * 1024: # 50MB
+ return False, "Arquivo muito grande (máx: 50MB)"
+
+ return True, ""
+
+ def process_file(
+ self,
+ file_path: Path,
+ profile_name: str = "custom_data",
+ content_type: str = "custom_ingestion", # 🆕 NOVO PARÂMETRO
+ **kwargs
+ ) -> tuple[List[Dict[str, Any]], str]:
+ """
+ Processa arquivo baseado na extensão.
+
+ Args:
+ file_path: Caminho do arquivo
+ profile_name: Nome do perfil/fonte
+ content_type: Tipo de conteúdo customizado
+ **kwargs: Argumentos específicos por formato
+
+ Returns:
+ (documents, status_message)
+ """
+ # Valida arquivo
+ is_valid, error = self.validate_file(file_path)
+ if not is_valid:
+ return [], f"❌ Erro: {error}"
+
+ try:
+ extension = file_path.suffix.lower()
+
+ if extension == '.json':
+ docs = self.ingest_json(file_path, profile_name, content_type)
+ elif extension == '.csv':
+ # CSV aceita: text_column, title_column, date_column
+ csv_kwargs = {
+ k: v for k, v in kwargs.items()
+ if k in ['text_column', 'title_column', 'date_column']
+ }
+ docs = self.ingest_csv(file_path, profile_name, content_type, **csv_kwargs)
+ elif extension == '.txt':
+ # TXT aceita apenas: split_by
+ txt_kwargs = {
+ k: v for k, v in kwargs.items()
+ if k in ['split_by']
+ }
+ docs = self.ingest_text(file_path, profile_name, content_type, **txt_kwargs)
+ elif extension == '.pdf':
+ # PDF não aceita kwargs extras
+ docs = self.ingest_pdf(file_path, profile_name, content_type)
+ else:
+ return [], f"❌ Formato {extension} não implementado"
+
+ return docs, f"✅ {len(docs)} registros processados com sucesso"
+
+ except Exception as e:
+ return [], f"❌ Erro ao processar: {str(e)}"
+
+
+def main():
+ """Teste do módulo."""
+ ingestion = DataIngestion()
+
+ print("Formatos suportados:")
+ for fmt in ingestion.get_supported_formats():
+ print(f" - {fmt}")
+
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
diff --git a/data_loader.py b/data_loader.py
index 661e8aa..d5dc01f 100644
--- a/data_loader.py
+++ b/data_loader.py
@@ -306,6 +306,50 @@ def get_profile_stats(self) -> Dict[str, Any]:
stats[profile]['date_range']['newest'] = post_date
return stats
+
+ def _process_instagram_post(self, post: Dict, profile: str) -> Dict[str, Any]:
+ """
+ Processa um post do Instagram.
+
+ Args:
+ post: Dados do post
+ profile: Nome do perfil
+
+ Returns:
+ Dicionário com dados processados
+ """
+ # Extrai dados principais
+ caption = post.get('caption', '')
+ hashtags = ' '.join(post.get('hashtags', []))
+ mentions = ' '.join(post.get('mentions', []))
+
+ # 🆕 Extrai comentários se disponíveis
+ comments = post.get('comments', [])
+ comments_text = ''
+ if comments:
+ # Concatena texto de todos os comentários
+ comments_list = [c.get('text', '') for c in comments if isinstance(c, dict) and c.get('text')]
+ comments_text = '\n'.join(comments_list)
+
+ # 🆕 Texto completo: legenda + comentários
+ full_text = f"Perfil: {profile}\nData: {post.get('timestamp', '')}\n\n=== LEGENDA ===\n{caption}\nHashtags: {hashtags}"
+
+ if comments_text:
+ full_text += f"\n\n=== COMENTÁRIOS ===\n{comments_text}"
+
+ return {
+ 'text': full_text,
+ 'profile': profile,
+ 'url': post.get('url', ''),
+ 'timestamp': post.get('timestamp', ''),
+ 'likesCount': post.get('likesCount', 0),
+ 'commentsCount': post.get('commentsCount', 0),
+ 'caption': caption, # 🆕 Armazena separadamente
+ 'hashtags': hashtags,
+ 'mentions': mentions,
+ 'comments_text': comments_text, # 🆕 Armazena separadamente
+ 'content_type': 'instagram_post'
+ }
def main():
diff --git a/pyproject.toml b/pyproject.toml
index 949a616..f2235c9 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,7 +1,7 @@
[project]
name = "ping"
version = "3.0.0"
-description = "PING - UFF ANALYTICS: Sistema RAG com IA (DeepSeek Chat + Ollama Embeddings)"
+description = "PING - UFF ANALYTICS"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
@@ -9,9 +9,12 @@ dependencies = [
"chromadb>=0.4.0",
"langchain>=0.1.0",
"langchain-community>=0.0.10",
- "ollama>=0.1.0", # Local embeddings only
- "openai>=1.0.0", # DeepSeek Chat API
- "ddgs>=3.9.0", # DuckDuckGo web search (novo nome)
+ "ollama>=0.1.0", # Local embeddings only
+ "openai>=1.0.0", # DeepSeek Chat API
+ "ddgs>=3.9.0", # DuckDuckGo web search (novo nome)
"python-dateutil>=2.8.0",
"emoji>=2.0.0",
+ "reportlab>=4.4.4",
+ "nltk>=3.8.0", # Natural Language Toolkit para stopwords
+ "pypdf2>=3.0.0", # Para leitura de PDFs
]
diff --git a/query_tools.py b/query_tools.py
index cd63786..3a8be17 100644
--- a/query_tools.py
+++ b/query_tools.py
@@ -525,6 +525,8 @@ def analyze_sentiment(
- neutral_count: Número de posts neutros
- key_points: Pontos-chave identificados
- examples: Exemplos de posts por sentimento
+ - hashtag_analysis: Análise de hashtags mais usadas ⭐ NOVO
+ - mention_analysis: Análise de menções mais frequentes ⭐ NOVO
"""
try:
# Busca posts relacionados ao tópico
@@ -557,30 +559,94 @@ def analyze_sentiment(
'negative_count': 0,
'neutral_count': 0,
'key_points': [],
- 'examples': {'positive': [], 'negative': [], 'neutral': []}
+ 'examples': {'positive': [], 'negative': [], 'neutral': []},
+ 'hashtag_analysis': {},
+ 'mention_analysis': {}
}
# Limita ao número solicitado
posts_to_analyze = relevant_posts[:n_posts]
- # Prepara contexto para o LLM
+ # ⭐ NOVA FUNCIONALIDADE: Análise de Hashtags
+ hashtag_counter = {}
+ for post in posts_to_analyze:
+ metadata = post.get('metadata', {})
+ hashtags = metadata.get('hashtags', [])
+ for tag in hashtags:
+ tag_lower = tag.lower()
+ hashtag_counter[tag_lower] = hashtag_counter.get(tag_lower, 0) + 1
+
+ # Top 10 hashtags mais usadas
+ top_hashtags = sorted(
+ hashtag_counter.items(),
+ key=lambda x: x[1],
+ reverse=True
+ )[:10]
+
+ hashtag_analysis = {
+ 'total_unique': len(hashtag_counter),
+ 'total_occurrences': sum(hashtag_counter.values()),
+ 'top_hashtags': [
+ {'tag': tag, 'count': count, 'percentage': round(count/len(posts_to_analyze)*100, 1)}
+ for tag, count in top_hashtags
+ ],
+ 'avg_per_post': round(sum(hashtag_counter.values()) / len(posts_to_analyze), 2)
+ }
+
+ # ⭐ NOVA FUNCIONALIDADE: Análise de Menções
+ mention_counter = {}
+ for post in posts_to_analyze:
+ metadata = post.get('metadata', {})
+ mentions = metadata.get('mentions', [])
+ for mention in mentions:
+ mention_clean = mention.replace('@', '').lower()
+ mention_counter[mention_clean] = mention_counter.get(mention_clean, 0) + 1
+
+ # Top 10 menções mais frequentes
+ top_mentions = sorted(
+ mention_counter.items(),
+ key=lambda x: x[1],
+ reverse=True
+ )[:10]
+
+ mention_analysis = {
+ 'total_unique': len(mention_counter),
+ 'total_occurrences': sum(mention_counter.values()),
+ 'top_mentions': [
+ {'username': f"@{user}", 'count': count, 'percentage': round(count/len(posts_to_analyze)*100, 1)}
+ for user, count in top_mentions
+ ],
+ 'avg_per_post': round(sum(mention_counter.values()) / len(posts_to_analyze), 2)
+ }
+
+ # Prepara contexto para o LLM (incluindo análise de hashtags/menções)
posts_text = "\n\n".join([
f"Post {i+1} (@{p['metadata']['profile']}):\n{p['document'][:500]}"
for i, p in enumerate(posts_to_analyze)
])
+ # Adiciona contexto de hashtags e menções ao prompt
+ social_context = f"""
+
+CONTEXTO SOCIAL DOS POSTS:
+- Hashtags mais usadas: {', '.join([f"#{tag}" for tag, _ in top_hashtags[:5]])}
+- Menções mais frequentes: {', '.join([f"@{user}" for user, _ in top_mentions[:5]])}
+- Média de hashtags por post: {hashtag_analysis['avg_per_post']}
+- Média de menções por post: {mention_analysis['avg_per_post']}
+"""
+
# Prompt para análise de sentimento
prompt = f"""Analise o sentimento dos posts abaixo sobre o tópico "{topic}".
-
+{social_context}
POSTS:
{posts_text}
Forneça uma análise estruturada em formato JSON com:
-1. sentiment_summary: Resumo geral do sentimento (2-3 frases)
+1. sentiment_summary: Resumo geral do sentimento (2-3 frases), considerando também as hashtags e menções usadas
2. positive_count: Número de posts com tom positivo/favorável
3. negative_count: Número de posts com tom negativo/crítico
4. neutral_count: Número de posts com tom neutro/informativo
-5. key_points: Lista de 3-5 pontos-chave sobre como o tópico é abordado
+5. key_points: Lista de 3-5 pontos-chave sobre como o tópico é abordado (inclua observações sobre hashtags/menções se relevante)
6. positive_aspects: Lista de aspectos positivos mencionados
7. negative_aspects: Lista de aspectos negativos/críticas mencionadas
@@ -645,7 +711,9 @@ def analyze_sentiment(
'key_points': analysis.get('key_points', []),
'positive_aspects': analysis.get('positive_aspects', []),
'negative_aspects': analysis.get('negative_aspects', []),
- 'examples': examples
+ 'examples': examples,
+ 'hashtag_analysis': hashtag_analysis, # ⭐ NOVO
+ 'mention_analysis': mention_analysis # ⭐ NOVO
}
except json.JSONDecodeError as e:
@@ -666,7 +734,9 @@ def analyze_sentiment(
'positive_aspects': [],
'negative_aspects': [],
'examples': {'positive': posts_to_analyze[:2], 'negative': [], 'neutral': []},
- 'error': 'LLM response parsing failed'
+ 'error': 'LLM response parsing failed',
+ 'hashtag_analysis': hashtag_analysis,
+ 'mention_analysis': mention_analysis
}
except Exception as e:
@@ -683,7 +753,9 @@ def analyze_sentiment(
'positive_aspects': [],
'negative_aspects': [],
'examples': {'positive': [], 'negative': [], 'neutral': []},
- 'error': str(e)
+ 'error': str(e),
+ 'hashtag_analysis': {},
+ 'mention_analysis': {}
}
diff --git a/reindex_with_news.py b/reindex_with_news.py
index 2d8b6e2..3510ab3 100755
--- a/reindex_with_news.py
+++ b/reindex_with_news.py
@@ -5,39 +5,31 @@
from data_loader import InstagramDataLoader
from embedding_manager import EmbeddingManager
+from sentiment_cache import SentimentCache
import sys
def main():
"""Reindexar posts e notícias."""
print("=" * 60)
- print(" 🔄 REINDEXAÇÃO COM NOTÍCIAS")
+ print(" 🔄 REINDEXAÇÃO DO BANCO VETORIAL")
print("=" * 60)
print()
- # Confirma
- print("⚠️ ATENÇÃO: Este script vai APAGAR o banco vetorial atual e reindexar tudo.")
- print(" Isso inclui:")
- print(" - Todos os posts do Instagram (dceuff, reitor, vicereitor)")
- print(" - Todas as notícias sobre Roberto Salles (_smoking_gun.json)")
- print()
-
- resposta = input("Deseja continuar? (sim/não): ").strip().lower()
-
- if resposta not in ['sim', 's', 'yes', 'y']:
- print("❌ Operação cancelada.")
- sys.exit(0)
-
- print()
- print("🔧 Inicializando componentes...")
-
- # Inicializa
+ # Inicializa componentes
+ print("🛠️ Inicializando componentes...")
loader = InstagramDataLoader()
em = EmbeddingManager()
-
print("✓ Componentes inicializados")
print()
+ # 🆕 Limpa cache de sentimento
+ print("🗑️ Limpando cache de análise de sentimento...")
+ cache = SentimentCache()
+ cache.clear_all()
+ print("✓ Cache limpo")
+ print()
+
# Limpa coleção atual
print("🗑️ Limpando banco vetorial atual...")
em.clear_collection()
diff --git a/report_exporter.py b/report_exporter.py
new file mode 100644
index 0000000..8724ec9
--- /dev/null
+++ b/report_exporter.py
@@ -0,0 +1,785 @@
+"""
+Módulo para exportação de relatórios do dashboard.
+Suporta formatos PDF e CSV.
+"""
+
+from typing import Dict, Any, Optional
+from datetime import datetime
+import csv
+import io
+from reportlab.lib import colors
+from reportlab.lib.pagesizes import A4, letter
+from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer, PageBreak
+from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
+from reportlab.lib.units import inch
+from reportlab.lib.enums import TA_CENTER, TA_LEFT
+
+
+class ReportExporter:
+ """Exportador de relatórios do dashboard."""
+
+ @staticmethod
+ def export_to_csv(metrics: Dict[str, Any], filename: Optional[str] = None) -> str:
+ """
+ Exporta métricas para CSV.
+
+ Args:
+ metrics: Dicionário de métricas do DashboardAnalytics
+ filename: Nome do arquivo (None = gera automaticamente)
+
+ Returns:
+ Conteúdo CSV como string
+ """
+ if filename is None:
+ timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
+ filename = f"relatorio_uff_{timestamp}.csv"
+
+ output = io.StringIO()
+ writer = csv.writer(output)
+
+ # Cabeçalho
+ writer.writerow(['RELATÓRIO DE ANÁLISE - PING UFF ANALYTICS'])
+ writer.writerow(['Gerado em:', datetime.now().strftime('%d/%m/%Y às %H:%M:%S')])
+ writer.writerow([])
+
+ # Resumo Geral
+ summary = metrics.get('summary', {})
+ writer.writerow(['=== RESUMO GERAL ==='])
+ writer.writerow(['Total de Registros:', summary.get('total_records', 0)])
+ writer.writerow(['Posts:', summary.get('posts_count', 0)])
+ writer.writerow(['Notícias:', summary.get('news_count', 0)])
+ writer.writerow(['Engajamento Total:', summary.get('total_engagement', 0)])
+ writer.writerow(['Média de Engajamento:', summary.get('avg_engagement_per_post', 0)])
+ writer.writerow([])
+
+ # Métricas de Posts
+ posts_data = metrics.get('posts', {})
+ writer.writerow(['=== MÉTRICAS DE POSTS ==='])
+ writer.writerow(['Total de Curtidas:', posts_data.get('total_likes', 0)])
+ writer.writerow(['Total de Comentários:', posts_data.get('total_comments', 0)])
+ writer.writerow(['Média de Curtidas:', posts_data.get('avg_likes', 0)])
+ writer.writerow(['Média de Comentários:', posts_data.get('avg_comments', 0)])
+ writer.writerow([])
+
+ # Distribuição por Perfil
+ writer.writerow(['=== DISTRIBUIÇÃO POR PERFIL ==='])
+ writer.writerow(['Perfil', 'Posts', 'Curtidas', 'Comentários', 'Engajamento'])
+ for profile, data in posts_data.get('by_profile', {}).items():
+ writer.writerow([
+ f"@{profile}",
+ data.get('count', 0),
+ data.get('likes', 0),
+ data.get('comments', 0),
+ data.get('engagement', 0)
+ ])
+ writer.writerow([])
+
+ # Top Posts por Engajamento
+ writer.writerow(['=== TOP 5 POSTS POR ENGAJAMENTO ==='])
+ writer.writerow(['Perfil', 'Curtidas', 'Comentários', 'Engajamento', 'Legenda', 'URL'])
+ for post in posts_data.get('top_by_engagement', [])[:5]:
+ writer.writerow([
+ f"@{post.get('profile', '')}",
+ post.get('likes', 0),
+ post.get('comments', 0),
+ post.get('engagement', 0),
+ post.get('caption', '')[:100],
+ post.get('url', '')
+ ])
+ writer.writerow([])
+
+ # Análise de Sentimento
+ sentiment = metrics.get('sentiment', {})
+ if sentiment.get('total_analyzed', 0) > 0:
+ writer.writerow(['=== ANÁLISE DE SENTIMENTO ==='])
+ writer.writerow(['Total Analisado:', sentiment.get('total_analyzed', 0)])
+ writer.writerow(['Positivo:', f"{sentiment.get('positive', 0)} ({sentiment.get('positive_pct', 0)}%)"])
+ writer.writerow(['Negativo:', f"{sentiment.get('negative', 0)} ({sentiment.get('negative_pct', 0)}%)"])
+ writer.writerow(['Neutro:', f"{sentiment.get('neutral', 0)} ({sentiment.get('neutral_pct', 0)}%)"])
+ writer.writerow(['Tendência:', sentiment.get('trend', 'N/A').upper()])
+ writer.writerow([])
+
+ # Tópicos Emergentes
+ emerging = metrics.get('emerging_topics', {})
+ if emerging.get('total_topics', 0) > 0:
+ writer.writerow(['=== TÓPICOS EMERGENTES ==='])
+ writer.writerow(['Termo', 'Menções', 'Percentual', 'Indicador'])
+ for topic in emerging.get('topics', [])[:10]:
+ writer.writerow([
+ topic.get('term', ''),
+ topic.get('count', 0),
+ f"{topic.get('percentage', 0)}%",
+ topic.get('growth_indicator', 0)
+ ])
+ writer.writerow([])
+
+ # Notícias
+ news_data = metrics.get('news', {})
+ if news_data.get('total', 0) > 0:
+ writer.writerow(['=== NOTÍCIAS ==='])
+ writer.writerow(['Total de Notícias:', news_data.get('total', 0)])
+ writer.writerow([])
+ writer.writerow(['Publisher', 'Quantidade'])
+ for publisher, count in sorted(
+ news_data.get('by_publisher', {}).items(),
+ key=lambda x: x[1],
+ reverse=True
+ )[:10]:
+ writer.writerow([publisher, count])
+
+ # 🆕 Recomendações de Políticas
+ recommendations = metrics.get('policy_recommendations', {})
+ if recommendations.get('has_recommendations', False):
+ writer.writerow(['=== RECOMENDAÇÕES DE POLÍTICAS ==='])
+ writer.writerow(['Gerado em:', recommendations.get('generated_at', 'N/A')])
+ writer.writerow(['Perfil:', recommendations.get('profile', 'N/A')])
+ writer.writerow([])
+
+ writer.writerow(['RESUMO DAS CRÍTICAS:'])
+ writer.writerow([recommendations.get('summary', '')])
+ writer.writerow([])
+
+ # Áreas críticas
+ writer.writerow(['ÁREAS PROBLEMÁTICAS IDENTIFICADAS:'])
+ writer.writerow(['Área', 'Frequência', 'Exemplos'])
+ for area in recommendations.get('critical_areas', []):
+ examples = ' | '.join(area.get('examples', [])[:2])
+ writer.writerow([
+ area.get('area', ''),
+ area.get('frequency', ''),
+ examples
+ ])
+ writer.writerow([])
+
+ # Recomendações
+ writer.writerow(['RECOMENDAÇÕES DE AÇÕES:'])
+ writer.writerow(['Prioridade', 'Área', 'Ação', 'Impacto Esperado', 'Prazo', 'Responsável'])
+ for rec in recommendations.get('recommendations', []):
+ writer.writerow([
+ rec.get('priority', ''),
+ rec.get('area', ''),
+ rec.get('action', ''),
+ rec.get('expected_impact', ''),
+ rec.get('implementation_time', ''),
+ rec.get('responsible', '')
+ ])
+ writer.writerow([])
+
+ # Aspectos positivos
+ if recommendations.get('positive_aspects'):
+ writer.writerow(['ASPECTOS POSITIVOS A MANTER:'])
+ for aspect in recommendations.get('positive_aspects', []):
+ writer.writerow(['•', aspect])
+ writer.writerow([])
+
+ # Observações gerais
+ writer.writerow(['OBSERVAÇÕES GERAIS:'])
+ writer.writerow([recommendations.get('general_observations', '')])
+ writer.writerow([])
+
+ content = output.getvalue()
+ output.close()
+
+ return content
+
+ @staticmethod
+ def export_to_pdf(metrics: Dict[str, Any], filename: Optional[str] = None) -> bytes:
+ """
+ Exporta métricas para PDF.
+
+ Args:
+ metrics: Dicionário de métricas do DashboardAnalytics
+ filename: Nome do arquivo (None = gera automaticamente)
+
+ Returns:
+ Bytes do PDF
+ """
+ if filename is None:
+ timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
+ filename = f"relatorio_uff_{timestamp}.pdf"
+
+ # Buffer de memória
+ buffer = io.BytesIO()
+
+ # Cria documento
+ doc = SimpleDocTemplate(
+ buffer,
+ pagesize=A4,
+ rightMargin=72,
+ leftMargin=72,
+ topMargin=72,
+ bottomMargin=72
+ )
+
+ # Estilos
+ styles = getSampleStyleSheet()
+ title_style = ParagraphStyle(
+ 'CustomTitle',
+ parent=styles['Heading1'],
+ fontSize=24,
+ textColor=colors.HexColor('#667eea'),
+ spaceAfter=30,
+ alignment=TA_CENTER
+ )
+
+ heading_style = ParagraphStyle(
+ 'CustomHeading',
+ parent=styles['Heading2'],
+ fontSize=16,
+ textColor=colors.HexColor('#764ba2'),
+ spaceAfter=12,
+ spaceBefore=12
+ )
+
+ # Elementos do PDF
+ elements = []
+
+ # Título
+ elements.append(Paragraph("📊 RELATÓRIO DE ANÁLISE", title_style))
+ elements.append(Paragraph("PING - UFF ANALYTICS", title_style))
+ elements.append(Spacer(1, 0.2*inch))
+
+ # Data de geração
+ date_text = f"Gerado em: {datetime.now().strftime('%d/%m/%Y às %H:%M:%S')}"
+ elements.append(Paragraph(date_text, styles['Normal']))
+ elements.append(Spacer(1, 0.3*inch))
+
+ # Resumo Geral
+ summary = metrics.get('summary', {})
+ elements.append(Paragraph("RESUMO GERAL", heading_style))
+
+ summary_data = [
+ ['Métrica', 'Valor'],
+ ['Total de Registros', f"{summary.get('total_records', 0):,}"],
+ ['Posts', f"{summary.get('posts_count', 0):,}"],
+ ['Notícias', f"{summary.get('news_count', 0):,}"],
+ ['Engajamento Total', f"{summary.get('total_engagement', 0):,}"],
+ ['Média de Engajamento', f"{summary.get('avg_engagement_per_post', 0):.2f}"]
+ ]
+
+ summary_table = Table(summary_data, colWidths=[3*inch, 2*inch])
+ summary_table.setStyle(TableStyle([
+ ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#667eea')),
+ ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
+ ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
+ ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
+ ('FONTSIZE', (0, 0), (-1, 0), 12),
+ ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
+ ('BACKGROUND', (0, 1), (-1, -1), colors.beige),
+ ('GRID', (0, 0), (-1, -1), 1, colors.black)
+ ]))
+
+ elements.append(summary_table)
+ elements.append(Spacer(1, 0.3*inch))
+
+ # Distribuição por Perfil
+ posts_data = metrics.get('posts', {})
+ if posts_data.get('by_profile'):
+ elements.append(Paragraph("DISTRIBUIÇÃO POR PERFIL", heading_style))
+
+ profile_data = [['Perfil', 'Posts', 'Curtidas', 'Comentários', 'Engajamento']]
+ for profile, data in sorted(
+ posts_data.get('by_profile', {}).items(),
+ key=lambda x: x[1]['engagement'],
+ reverse=True
+ ):
+ profile_data.append([
+ f"@{profile}",
+ f"{data.get('count', 0):,}",
+ f"{data.get('likes', 0):,}",
+ f"{data.get('comments', 0):,}",
+ f"{data.get('engagement', 0):,}"
+ ])
+
+ profile_table = Table(profile_data, colWidths=[1.5*inch, 1*inch, 1*inch, 1*inch, 1.2*inch])
+ profile_table.setStyle(TableStyle([
+ ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#764ba2')),
+ ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
+ ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
+ ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
+ ('FONTSIZE', (0, 0), (-1, 0), 10),
+ ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
+ ('BACKGROUND', (0, 1), (-1, -1), colors.lavender),
+ ('GRID', (0, 0), (-1, -1), 1, colors.black)
+ ]))
+
+ elements.append(profile_table)
+ elements.append(Spacer(1, 0.3*inch))
+
+ # Análise de Sentimento
+ sentiment = metrics.get('sentiment', {})
+ if sentiment.get('total_analyzed', 0) > 0:
+ elements.append(Paragraph("ANÁLISE DE SENTIMENTO", heading_style))
+
+ sentiment_data = [
+ ['Categoria', 'Quantidade', 'Percentual'],
+ ['Positivo', f"{sentiment.get('positive', 0):,}", f"{sentiment.get('positive_pct', 0)}%"],
+ ['Negativo', f"{sentiment.get('negative', 0):,}", f"{sentiment.get('negative_pct', 0)}%"],
+ ['Neutro', f"{sentiment.get('neutral', 0):,}", f"{sentiment.get('neutral_pct', 0)}%"],
+ ['TENDÊNCIA', sentiment.get('trend', 'N/A').upper(), '-']
+ ]
+
+ sentiment_table = Table(sentiment_data, colWidths=[2*inch, 1.5*inch, 1.5*inch])
+ sentiment_table.setStyle(TableStyle([
+ ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#4caf50')),
+ ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
+ ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
+ ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
+ ('FONTSIZE', (0, 0), (-1, 0), 10),
+ ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
+ ('BACKGROUND', (0, 1), (-1, -1), colors.lightgreen),
+ ('BACKGROUND', (0, -1), (-1, -1), colors.HexColor('#ffd54f')),
+ ('FONTNAME', (0, -1), (-1, -1), 'Helvetica-Bold'),
+ ('GRID', (0, 0), (-1, -1), 1, colors.black)
+ ]))
+
+ elements.append(sentiment_table)
+ elements.append(Spacer(1, 0.3*inch))
+
+ # Tópicos Emergentes
+ emerging = metrics.get('emerging_topics', {})
+ if emerging.get('total_topics', 0) > 0:
+ elements.append(PageBreak())
+ elements.append(Paragraph("TÓPICOS EMERGENTES", heading_style))
+
+ topics_data = [['#', 'Termo', 'Menções', '%']]
+ for i, topic in enumerate(emerging.get('topics', [])[:10], 1):
+ topics_data.append([
+ str(i),
+ topic.get('term', ''),
+ f"{topic.get('count', 0):,}",
+ f"{topic.get('percentage', 0)}%"
+ ])
+
+ topics_table = Table(topics_data, colWidths=[0.5*inch, 2*inch, 1.2*inch, 1*inch])
+ topics_table.setStyle(TableStyle([
+ ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#ff9800')),
+ ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
+ ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
+ ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
+ ('FONTSIZE', (0, 0), (-1, 0), 10),
+ ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
+ ('BACKGROUND', (0, 1), (-1, -1), colors.HexColor('#ffe0b2')),
+ ('GRID', (0, 0), (-1, -1), 1, colors.black)
+ ]))
+
+ elements.append(topics_table)
+ elements.append(Spacer(1, 0.3*inch))
+
+ # 🆕 Recomendações de Políticas
+ recommendations = metrics.get('policy_recommendations', {})
+ if recommendations.get('has_recommendations', False):
+ elements.append(PageBreak())
+ elements.append(Paragraph("RECOMENDAÇÕES DE POLÍTICAS", heading_style))
+
+ # Resumo
+ summary_text = f"""
+ Resumo das Críticas:
+ {recommendations.get('summary', 'N/A')}
+ """
+ elements.append(Paragraph(summary_text, styles['Normal']))
+ elements.append(Spacer(1, 0.2*inch))
+
+ # Áreas Críticas - FORMATO DE CARDS
+ elements.append(Paragraph("Áreas Problemáticas Identificadas", styles['Heading3']))
+ elements.append(Spacer(1, 0.2*inch))
+
+ # Estilo para cards de áreas problemáticas
+ problem_card_style = ParagraphStyle(
+ 'ProblemCardStyle',
+ parent=styles['Normal'],
+ fontSize=10,
+ leading=14,
+ spaceAfter=6,
+ leftIndent=10,
+ rightIndent=10
+ )
+
+ problem_card_title_style = ParagraphStyle(
+ 'ProblemCardTitle',
+ parent=styles['Heading3'],
+ fontSize=12,
+ textColor=colors.HexColor('#f44336'),
+ spaceAfter=8,
+ spaceBefore=0
+ )
+
+ # Itera sobre cada área problemática criando um card
+ for i, area in enumerate(recommendations.get('critical_areas', []), 1):
+ area_name = area.get('area', 'N/A')
+ frequency = area.get('frequency', 'N/A').upper()
+ examples = area.get('examples', [])
+
+ # Define cor da frequência
+ if frequency == 'ALTA':
+ freq_color = colors.HexColor('#d32f2f')
+ bg_color = colors.HexColor('#ffebee')
+ elif frequency == 'MÉDIA':
+ freq_color = colors.HexColor('#f57c00')
+ bg_color = colors.HexColor('#fff3e0')
+ else:
+ freq_color = colors.HexColor('#1976d2')
+ bg_color = colors.HexColor('#e3f2fd')
+
+ # Card header
+ card_header = f"""
+
+
+ ⚠️ ÁREA PROBLEMÁTICA {i} - FREQUÊNCIA {frequency}
+
+
+ """
+
+ # Card content
+ card_content = f"""
+ Área Identificada:
+ {area_name}
+
+ Exemplos Observados:
+ """
+
+ # Adiciona exemplos como bullets
+ for j, example in enumerate(examples[:3], 1):
+ card_content += f"• {example}
"
+
+ # Adiciona elementos do card
+ elements.append(Paragraph(card_header, problem_card_title_style))
+
+ # Cria card com borda e fundo colorido
+ card_data = [[Paragraph(card_content, problem_card_style)]]
+ card_table = Table(card_data, colWidths=[6.5*inch])
+ card_table.setStyle(TableStyle([
+ ('BACKGROUND', (0, 0), (-1, -1), bg_color),
+ ('BORDER', (0, 0), (-1, -1), 2, freq_color),
+ ('TOPPADDING', (0, 0), (-1, -1), 12),
+ ('BOTTOMPADDING', (0, 0), (-1, -1), 12),
+ ('LEFTPADDING', (0, 0), (-1, -1), 15),
+ ('RIGHTPADDING', (0, 0), (-1, -1), 15),
+ ('VALIGN', (0, 0), (-1, -1), 'TOP'),
+ ]))
+
+ elements.append(card_table)
+ elements.append(Spacer(1, 0.25*inch))
+
+ # Espaço após áreas problemáticas
+ elements.append(Spacer(1, 0.2*inch))
+
+ # 🆕 Recomendações em CARDS (texto corrido, mais legível)
+ elements.append(PageBreak())
+ elements.append(Paragraph("Ações Recomendadas", styles['Heading3']))
+ elements.append(Spacer(1, 0.2*inch))
+
+ # Estilo para cards de recomendações
+ card_style = ParagraphStyle(
+ 'CardStyle',
+ parent=styles['Normal'],
+ fontSize=10,
+ leading=14,
+ spaceAfter=6,
+ leftIndent=10,
+ rightIndent=10
+ )
+
+ card_title_style = ParagraphStyle(
+ 'CardTitle',
+ parent=styles['Heading3'],
+ fontSize=12,
+ textColor=colors.HexColor('#4caf50'),
+ spaceAfter=8,
+ spaceBefore=0
+ )
+
+ # Itera sobre cada recomendação criando um card
+ for i, rec in enumerate(recommendations.get('recommendations', []), 1):
+ priority = rec.get('priority', '').upper()
+ area = rec.get('area', 'N/A')
+ action = rec.get('action', 'N/A')
+ impact = rec.get('expected_impact', 'N/A')
+ time = rec.get('implementation_time', 'N/A')
+ responsible = rec.get('responsible', 'N/A')
+ reasoning = rec.get('reasoning', '')
+
+ # Define cor da prioridade
+ if priority == 'ALTA':
+ priority_color = colors.HexColor('#f44336')
+ bg_color = colors.HexColor('#ffebee')
+ elif priority == 'MÉDIA':
+ priority_color = colors.HexColor('#ff9800')
+ bg_color = colors.HexColor('#fff3e0')
+ else:
+ priority_color = colors.HexColor('#2196f3')
+ bg_color = colors.HexColor('#e3f2fd')
+
+ # Card container (tabela com fundo colorido)
+ card_header = f"""
+
+
+ 🎯 RECOMENDAÇÃO {i} - PRIORIDADE {priority}
+
+
+ """
+
+ card_content = f"""
+ Área de Atuação:
+ {area}
+
+ Ação Recomendada:
+ {action}
+
+ Impacto Esperado:
+ {impact}
+
+ Prazo de Implementação: {time.title()}
+ Responsável: {responsible}
+ """
+
+ if reasoning:
+ card_content += f"""
+
+ Justificativa:
+ {reasoning}
+ """
+
+ # Adiciona elementos do card
+ elements.append(Paragraph(card_header, card_title_style))
+
+ # Cria card com borda e fundo colorido
+ card_data = [[Paragraph(card_content, card_style)]]
+ card_table = Table(card_data, colWidths=[6.5*inch])
+ card_table.setStyle(TableStyle([
+ ('BACKGROUND', (0, 0), (-1, -1), bg_color),
+ ('BORDER', (0, 0), (-1, -1), 2, priority_color),
+ ('TOPPADDING', (0, 0), (-1, -1), 12),
+ ('BOTTOMPADDING', (0, 0), (-1, -1), 12),
+ ('LEFTPADDING', (0, 0), (-1, -1), 15),
+ ('RIGHTPADDING', (0, 0), (-1, -1), 15),
+ ('VALIGN', (0, 0), (-1, -1), 'TOP'),
+ ]))
+
+ elements.append(card_table)
+ elements.append(Spacer(1, 0.25*inch))
+
+ # Espaço após recomendações
+ elements.append(Spacer(1, 0.2*inch))
+
+ # Aspectos positivos
+ if recommendations.get('positive_aspects'):
+ elements.append(Paragraph("Aspectos Positivos a Manter", styles['Heading3']))
+ positive_text = "
".join([f"• {asp}" for asp in recommendations.get('positive_aspects', [])])
+ elements.append(Paragraph(positive_text, styles['Normal']))
+ elements.append(Spacer(1, 0.2*inch))
+
+ # Rodapé
+ elements.append(Spacer(1, 0.5*inch))
+ footer = Paragraph(
+ "Desenvolvido pelo CID - Centro de Inovação em Dados",
+ styles['Normal']
+ )
+ elements.append(footer)
+
+ # Constrói PDF
+ doc.build(elements)
+
+ # Retorna bytes
+ pdf_bytes = buffer.getvalue()
+ buffer.close()
+
+ return pdf_bytes
+
+
+def main():
+ """Função de teste."""
+ print("=== Testando Report Exporter ===\n")
+
+ # Mock data
+ mock_metrics = {
+ 'summary': {
+ 'total_records': 2500,
+ 'posts_count': 2400,
+ 'news_count': 100,
+ 'total_engagement': 150000,
+ 'avg_engagement_per_post': 62.5
+ },
+ 'posts': {
+ 'total': 2400,
+ 'total_likes': 120000,
+ 'total_comments': 30000,
+ 'avg_likes': 50.0,
+ 'avg_comments': 12.5,
+ 'by_profile': {
+ 'dceuff': {'count': 1500, 'likes': 75000, 'comments': 18000, 'engagement': 93000},
+ 'reitor': {'count': 600, 'likes': 30000, 'comments': 8000, 'engagement': 38000},
+ 'vicereitor': {'count': 300, 'likes': 15000, 'comments': 4000, 'engagement': 19000}
+ },
+ 'top_by_engagement': [
+ {
+ 'profile': 'dceuff',
+ 'likes': 500,
+ 'comments': 120,
+ 'engagement': 620,
+ 'url': 'https://instagram.com/p/test1',
+ 'caption': 'Post de teste...'
+ }
+ ]
+ },
+ 'sentiment': {
+ 'total_analyzed': 100,
+ 'positive': 35,
+ 'negative': 45,
+ 'neutral': 20,
+ 'positive_pct': 35.0,
+ 'negative_pct': 45.0,
+ 'neutral_pct': 20.0,
+ 'trend': 'negative'
+ },
+ 'emerging_topics': {
+ 'total_topics': 5,
+ 'topics': [
+ {'term': 'greve', 'count': 156, 'percentage': 6.5},
+ {'term': 'HUAP', 'count': 134, 'percentage': 5.6}
+ ]
+ },
+ 'news': {
+ 'total': 100,
+ 'by_publisher': {
+ 'G1': 30,
+ 'Folha': 25
+ }
+ },
+ 'policy_recommendations': {
+ 'has_recommendations': True,
+ 'generated_at': '2023-10-10 10:00:00',
+ 'profile': 'dceuff',
+ 'summary': 'Críticas construtivas sobre a gestão de conteúdo.',
+ 'critical_areas': [
+ {
+ 'area': 'Falta de interatividade',
+ 'frequency': 'Alta',
+ 'examples': ['Post sem enquetes', 'Stories sem perguntas']
+ },
+ {
+ 'area': 'Baixo engajamento em posts',
+ 'frequency': 'Média',
+ 'examples': ['Posts com menos de 10 curtidas']
+ }
+ ],
+ 'recommendations': [
+ {
+ 'priority': 'Alta',
+ 'area': 'Conteúdo',
+ 'action': 'Criar enquetes nos stories',
+ 'expected_impact': 'Aumentar a interatividade',
+ 'implementation_time': 'Imediato',
+ 'responsible': 'Equipe de Conteúdo'
+ },
+ {
+ 'priority': 'Média',
+ 'area': 'Postagens',
+ 'action': 'Revisar horários de postagem',
+ 'expected_impact': 'Aumentar o alcance',
+ 'implementation_time': '1 semana',
+ 'responsible': 'Social Media'
+ }
+ ],
+ 'positive_aspects': [
+ 'Bom uso de imagens',
+ 'Legendas criativas'
+ ],
+ 'general_observations': 'Continuar o bom trabalho!'
+ }
+ }
+
+ # Testa CSV
+ print("📄 Gerando CSV...")
+ csv_content = ReportExporter.export_to_csv(mock_metrics)
+ with open('test_relatorio.csv', 'w', encoding='utf-8') as f:
+ f.write(csv_content)
+ print("✅ CSV gerado: test_relatorio.csv")
+
+ # Testa PDF
+ print("\n📕 Gerando PDF...")
+ pdf_bytes = ReportExporter.export_to_pdf(mock_metrics)
+ with open('test_relatorio.pdf', 'wb') as f:
+ f.write(pdf_bytes)
+ print("✅ PDF gerado: test_relatorio.pdf")
+
+ # 🆕 Mock de recomendações
+ mock_metrics['policy_recommendations'] = {
+ 'has_recommendations': True,
+ 'generated_at': '2025-10-27T14:30:00',
+ 'profile': 'dceuff',
+ 'content_filter': 'both',
+ 'sentiment_data': {
+ 'total_analyzed': 100,
+ 'negative_pct': 45.0,
+ 'trend': 'negative'
+ },
+ 'summary': 'As principais críticas giram em torno de demora nas respostas institucionais, falta de transparência e problemas estruturais no HUAP.',
+ 'critical_areas': [
+ {
+ 'area': 'Comunicação Institucional',
+ 'frequency': 'alta',
+ 'examples': [
+ 'Falta de resposta aos questionamentos',
+ 'Informações desencontradas'
+ ]
+ },
+ {
+ 'area': 'Infraestrutura',
+ 'frequency': 'média',
+ 'examples': [
+ 'HUAP sem condições adequadas',
+ 'Falta de equipamentos'
+ ]
+ }
+ ],
+ 'recommendations': [
+ {
+ 'priority': 'alta',
+ 'area': 'Comunicação',
+ 'action': 'Implementar canal de respostas em até 48h',
+ 'expected_impact': 'Redução de 40% nas reclamações sobre falta de resposta',
+ 'implementation_time': 'curto prazo',
+ 'responsible': 'Assessoria de Comunicação'
+ },
+ {
+ 'priority': 'alta',
+ 'area': 'Transparência',
+ 'action': 'Criar dashboard público de acompanhamento de demandas',
+ 'expected_impact': 'Aumento de confiança e engajamento positivo',
+ 'implementation_time': 'médio prazo',
+ 'responsible': 'Diretoria de TI + Comunicação'
+ },
+ {
+ 'priority': 'média',
+ 'area': 'HUAP',
+ 'action': 'Divulgar calendário de melhorias e investimentos',
+ 'expected_impact': 'Redução de especulações negativas',
+ 'implementation_time': 'curto prazo',
+ 'responsible': 'Administração do HUAP'
+ }
+ ],
+ 'positive_aspects': [
+ 'Diálogo com movimentos estudantis',
+ 'Transparência em eventos públicos'
+ ],
+ 'general_observations': 'A gestão atual tem boa receptividade em eventos presenciais, mas precisa melhorar a comunicação digital e o tempo de resposta a questionamentos.'
+ }
+
+ # Testa CSV com novas recomendações
+ print("\n📄 Gerando CSV com Recomendações...")
+ csv_content = ReportExporter.export_to_csv(mock_metrics)
+ with open('test_relatorio_recomendacoes.csv', 'w', encoding='utf-8') as f:
+ f.write(csv_content)
+ print("✅ CSV gerado: test_relatorio_recomendacoes.csv")
+
+ # Testa PDF com novas recomendações
+ print("\n📕 Gerando PDF com Recomendações...")
+ pdf_bytes = ReportExporter.export_to_pdf(mock_metrics)
+ with open('test_relatorio_recomendacoes.pdf', 'wb') as f:
+ f.write(pdf_bytes)
+ print("✅ PDF gerado: test_relatorio_recomendacoes.pdf")
+
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index f3daf16..e5cf296 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -22,3 +22,5 @@ ddgs>=3.9.0 # DuckDuckGo web search (antigo: duckduckgo-search)
# Utilities
python-dateutil>=2.8.0
emoji>=2.0.0
+reportlab>=4.0.0
+nltk>=3.8.0 # Natural Language Toolkit para stopwords
diff --git a/sentiment_cache.py b/sentiment_cache.py
new file mode 100644
index 0000000..f7bd4e2
--- /dev/null
+++ b/sentiment_cache.py
@@ -0,0 +1,299 @@
+"""
+Sistema de cache para análises de sentimento.
+Evita recálculo quando os dados não mudarem.
+"""
+
+import json
+import hashlib
+from pathlib import Path
+from typing import Dict, Any, Optional
+from datetime import datetime
+
+
+class SentimentCache:
+ """Gerenciador de cache para análises de sentimento."""
+
+ def __init__(self, cache_dir: str = "./cache"):
+ """
+ Inicializa o cache.
+
+ Args:
+ cache_dir: Diretório para armazenar cache
+ """
+ self.cache_dir = Path(cache_dir)
+ self.cache_dir.mkdir(exist_ok=True)
+ self.cache_file = self.cache_dir / "sentiment_cache.json"
+ self.metadata_file = self.cache_dir / "cache_metadata.json"
+
+ self.cache = self._load_cache()
+ self.metadata = self._load_metadata()
+
+ def _load_cache(self) -> Dict[str, Any]:
+ """Carrega cache do disco."""
+ if self.cache_file.exists():
+ try:
+ with open(self.cache_file, 'r', encoding='utf-8') as f:
+ return json.load(f)
+ except Exception as e:
+ print(f"⚠️ Erro ao carregar cache: {e}")
+ return {}
+ return {}
+
+ def _load_metadata(self) -> Dict[str, Any]:
+ """Carrega metadados do cache."""
+ if self.metadata_file.exists():
+ try:
+ with open(self.metadata_file, 'r', encoding='utf-8') as f:
+ return json.load(f)
+ except Exception as e:
+ print(f"⚠️ Erro ao carregar metadata: {e}")
+ return {}
+ return {}
+
+ def _save_cache(self):
+ """Salva cache no disco."""
+ try:
+ with open(self.cache_file, 'w', encoding='utf-8') as f:
+ json.dump(self.cache, f, indent=2, ensure_ascii=False)
+ except Exception as e:
+ print(f"⚠️ Erro ao salvar cache: {e}")
+
+ def _save_metadata(self):
+ """Salva metadados no disco."""
+ try:
+ with open(self.metadata_file, 'w', encoding='utf-8') as f:
+ json.dump(self.metadata, f, indent=2, ensure_ascii=False)
+ except Exception as e:
+ print(f"⚠️ Erro ao salvar metadata: {e}")
+
+ def _generate_key(
+ self,
+ profile: Optional[str] = None,
+ start_date: Optional[str] = None,
+ end_date: Optional[str] = None,
+ total_docs: int = 0,
+ content_filter: str = "both" # 🆕 Filtro de conteúdo
+ ) -> str:
+ """
+ Gera chave única para a análise baseada nos parâmetros.
+
+ Args:
+ profile: Perfil filtrado
+ start_date: Data inicial
+ end_date: Data final
+ total_docs: Total de documentos analisados
+ content_filter: Tipo de conteúdo ("caption", "comments", "both")
+
+ Returns:
+ Hash MD5 como chave
+ """
+ key_parts = [
+ profile or "all",
+ start_date or "none",
+ end_date or "none",
+ str(total_docs),
+ content_filter # 🆕 Inclui no hash
+ ]
+ key_string = "|".join(key_parts)
+ return hashlib.md5(key_string.encode()).hexdigest()
+
+ def get(
+ self,
+ profile: Optional[str] = None,
+ start_date: Optional[str] = None,
+ end_date: Optional[str] = None,
+ total_docs: int = 0,
+ content_filter: str = "both" # 🆕 Filtro de conteúdo
+ ) -> Optional[Dict[str, Any]]:
+ """
+ Busca análise no cache.
+
+ Args:
+ profile: Perfil filtrado
+ start_date: Data inicial
+ end_date: Data final
+ total_docs: Total de documentos na análise
+ content_filter: Tipo de conteúdo ("caption", "comments", "both")
+
+ Returns:
+ Resultado do cache ou None se não encontrado/inválido
+ """
+ key = self._generate_key(profile, start_date, end_date, total_docs, content_filter)
+
+ if key not in self.cache:
+ return None
+
+ cached_entry = self.cache[key]
+
+ # Verifica se o total de documentos mudou (novos posts adicionados)
+ if cached_entry.get('total_docs') != total_docs:
+ print(f"🔄 Cache inválido: total de docs mudou ({cached_entry.get('total_docs')} → {total_docs})")
+ self.invalidate(profile, start_date, end_date, content_filter)
+ return None
+
+ # Cache válido
+ print(f"✅ Cache hit! Usando análise de {cached_entry.get('cached_at', 'N/A')}")
+ return cached_entry['result']
+
+ def set(
+ self,
+ result: Dict[str, Any],
+ profile: Optional[str] = None,
+ start_date: Optional[str] = None,
+ end_date: Optional[str] = None,
+ total_docs: int = 0,
+ content_filter: str = "both" # 🆕 Filtro de conteúdo
+ ):
+ """
+ Armazena análise no cache.
+
+ Args:
+ result: Resultado da análise
+ profile: Perfil filtrado
+ start_date: Data inicial
+ end_date: Data final
+ total_docs: Total de documentos analisados
+ content_filter: Tipo de conteúdo ("caption", "comments", "both")
+ """
+ key = self._generate_key(profile, start_date, end_date, total_docs, content_filter)
+
+ self.cache[key] = {
+ 'result': result,
+ 'profile': profile,
+ 'start_date': start_date,
+ 'end_date': end_date,
+ 'total_docs': total_docs,
+ 'content_filter': content_filter, # 🆕 Armazena filtro
+ 'cached_at': datetime.now().isoformat()
+ }
+
+ # Atualiza metadata
+ self.metadata[key] = {
+ 'profile': profile or 'all',
+ 'total_docs': total_docs,
+ 'content_filter': content_filter,
+ 'cached_at': datetime.now().isoformat()
+ }
+
+ self._save_cache()
+ self._save_metadata()
+
+ print(f"💾 Cache salvo para: perfil={profile or 'todos'}, docs={total_docs}, conteúdo={content_filter}")
+
+ def invalidate(
+ self,
+ profile: Optional[str] = None,
+ start_date: Optional[str] = None,
+ end_date: Optional[str] = None,
+ content_filter: Optional[str] = None # 🆕 Filtro de conteúdo
+ ):
+ """
+ Invalida entrada específica do cache.
+
+ Args:
+ profile: Perfil a invalidar
+ start_date: Data inicial
+ end_date: Data final
+ content_filter: Tipo de conteúdo (None = invalida todos)
+ """
+ # Invalida todas as entradas com os mesmos parâmetros (diferentes total_docs)
+ keys_to_remove = []
+
+ for key, entry in self.cache.items():
+ match = (
+ entry.get('profile') == profile and
+ entry.get('start_date') == start_date and
+ entry.get('end_date') == end_date
+ )
+
+ # Se content_filter especificado, filtra por ele também
+ if content_filter:
+ match = match and entry.get('content_filter') == content_filter
+
+ if match:
+ keys_to_remove.append(key)
+
+ for key in keys_to_remove:
+ del self.cache[key]
+ if key in self.metadata:
+ del self.metadata[key]
+
+ if keys_to_remove:
+ self._save_cache()
+ self._save_metadata()
+ print(f"🗑️ {len(keys_to_remove)} entrada(s) invalidada(s)")
+
+ def clear_all(self):
+ """Limpa todo o cache."""
+ self.cache = {}
+ self.metadata = {}
+ self._save_cache()
+ self._save_metadata()
+ print("🗑️ Cache completamente limpo")
+
+ def get_stats(self) -> Dict[str, Any]:
+ """
+ Retorna estatísticas do cache.
+
+ Returns:
+ Dict com estatísticas
+ """
+ total_entries = len(self.cache)
+
+ # Agrupa por perfil
+ by_profile = {}
+ for entry in self.cache.values():
+ prof = entry.get('profile') or 'all'
+ by_profile[prof] = by_profile.get(prof, 0) + 1
+
+ # Tamanho em disco
+ cache_size = 0
+ if self.cache_file.exists():
+ cache_size += self.cache_file.stat().st_size
+ if self.metadata_file.exists():
+ cache_size += self.metadata_file.stat().st_size
+
+ return {
+ 'total_entries': total_entries,
+ 'by_profile': by_profile,
+ 'cache_size_kb': round(cache_size / 1024, 2),
+ 'cache_dir': str(self.cache_dir)
+ }
+
+
+def main():
+ """Função de teste."""
+ print("=== Testando Sistema de Cache ===\n")
+
+ cache = SentimentCache()
+
+ # Teste 1: Salvar no cache
+ print("1. Salvando análise no cache...")
+ result = {
+ 'total_analyzed': 100,
+ 'positive': 30,
+ 'negative': 50,
+ 'neutral': 20,
+ 'trend': 'negative'
+ }
+ cache.set(result, profile="dceuff", total_docs=100)
+
+ # Teste 2: Recuperar do cache
+ print("\n2. Recuperando do cache...")
+ cached = cache.get(profile="dceuff", total_docs=100)
+ print(f"Resultado: {cached}")
+
+ # Teste 3: Cache miss (total_docs diferente)
+ print("\n3. Testando cache miss (novos posts)...")
+ cached = cache.get(profile="dceuff", total_docs=150)
+ print(f"Resultado: {cached}")
+
+ # Teste 4: Estatísticas
+ print("\n4. Estatísticas do cache:")
+ stats = cache.get_stats()
+ for key, value in stats.items():
+ print(f" {key}: {value}")
+
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/test_comment_filter.py b/test_comment_filter.py
new file mode 100644
index 0000000..1226514
--- /dev/null
+++ b/test_comment_filter.py
@@ -0,0 +1,103 @@
+"""
+Teste de diagnóstico: verifica estrutura dos dados para filtro de comentários.
+"""
+
+from embedding_manager import EmbeddingManager
+from analytics_dashboard import DashboardAnalytics
+import json
+
+def main():
+ print("=" * 60)
+ print("🔬 DIAGNÓSTICO: Estrutura de Dados para Comentários")
+ print("=" * 60)
+
+ em = EmbeddingManager()
+ analytics = DashboardAnalytics(em)
+
+ # Diagnóstico da estrutura
+ print("\n📊 Verificando estrutura dos primeiros 10 posts...\n")
+ diagnosis = analytics.diagnose_content_structure(limit=10)
+
+ print(f"Total verificado: {diagnosis['total_checked']} posts\n")
+
+ print("📈 Formatos encontrados:")
+ for format_name, count in diagnosis['formats_found'].items():
+ percentage = (count / diagnosis['total_checked'] * 100) if diagnosis['total_checked'] > 0 else 0
+ print(f" - {format_name}: {count} ({percentage:.1f}%)")
+
+ print("\n📋 Amostras dos documentos:\n")
+
+ for sample in diagnosis['samples']:
+ print(f"\n--- Post {sample['index'] + 1} (@{sample['profile']}) ---")
+ print(f"Chaves no metadata: {sample['metadata_keys']}")
+ print(f"Tem 'caption' no metadata: {sample['has_caption_key']}")
+ print(f"Tem 'comments_text' no metadata: {sample['has_comments_text_key']}")
+ print(f"Tem marcador '=== LEGENDA ===': {sample.get('has_legenda_marker', False)}")
+ print(f"Tem marcador '=== COMENTÁRIOS ===': {sample.get('has_comentarios_marker', False)}")
+ print(f"Tem formato alternativo: {sample.get('has_alt_format', False)}")
+ print(f"\nPreview do documento:")
+ print(sample['doc_preview'])
+ print("-" * 50)
+
+ # Teste de filtro com cada tipo
+ print("\n\n" + "=" * 60)
+ print("🧪 TESTE: Filtro de Sentimento por Tipo de Conteúdo")
+ print("=" * 60)
+
+ profile = "dceuff" # Ajuste conforme necessário
+
+ print(f"\n📊 Testando filtros para @{profile}:\n")
+
+ # Teste 1: Both
+ print("1️⃣ Filtro: BOTH (legendas + comentários)")
+ sentiment_both = analytics.get_sentiment_by_profile(
+ profile=profile,
+ content_filter="both",
+ use_cache=False,
+ use_llm=False # Usa keywords para ser rápido
+ )
+ print(f" ✅ Analisados: {sentiment_both.get('total_analyzed', 0)} registros")
+
+ # Teste 2: Caption only
+ print("\n2️⃣ Filtro: CAPTION (apenas legendas)")
+ sentiment_caption = analytics.get_sentiment_by_profile(
+ profile=profile,
+ content_filter="caption",
+ use_cache=False,
+ use_llm=False
+ )
+ print(f" ✅ Analisados: {sentiment_caption.get('total_analyzed', 0)} registros")
+
+ # Teste 3: Comments only
+ print("\n3️⃣ Filtro: COMMENTS (apenas comentários)")
+ sentiment_comments = analytics.get_sentiment_by_profile(
+ profile=profile,
+ content_filter="comments",
+ use_cache=False,
+ use_llm=False
+ )
+ print(f" ✅ Analisados: {sentiment_comments.get('total_analyzed', 0)} registros")
+
+ print("\n" + "=" * 60)
+ print("📝 CONCLUSÃO:")
+ print("=" * 60)
+
+ if sentiment_comments.get('total_analyzed', 0) == 0:
+ print("\n⚠️ PROBLEMA DETECTADO:")
+ print(" Filtro de comentários retornou 0 registros!")
+ print("\n💡 Possíveis causas:")
+ print(" 1. Posts não têm comentários no banco")
+ print(" 2. Formato de armazenamento diferente do esperado")
+ print(" 3. Metadata 'comments_text' não existe")
+ print("\n🔧 Próximos passos:")
+ print(" 1. Verificar data_loader.py (como posts são indexados)")
+ print(" 2. Verificar se comentários estão sendo salvos")
+ print(" 3. Reindexar dados se necessário")
+ else:
+ print(f"\n✅ Filtro funcionando! {sentiment_comments.get('total_analyzed', 0)} comentários encontrados")
+
+ print("\n" + "=" * 60)
+
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/test_critical_areas.py b/test_critical_areas.py
new file mode 100644
index 0000000..27587e2
--- /dev/null
+++ b/test_critical_areas.py
@@ -0,0 +1,109 @@
+#!/usr/bin/env python3
+"""
+Teste para verificar se as áreas críticas estão sendo geradas corretamente
+nas recomendações de políticas.
+"""
+
+import sys
+from analytics_dashboard import DashboardAnalytics
+from embedding_manager import EmbeddingManager
+from pathlib import Path
+
+
+def test_critical_areas():
+ """Testa se as áreas críticas são geradas corretamente."""
+ print("\n" + "="*60)
+ print("🧪 TESTE: Geração de Áreas Críticas")
+ print("="*60 + "\n")
+
+ try:
+ # Inicializa EmbeddingManager
+ print("📊 Inicializando EmbeddingManager...")
+ em = EmbeddingManager(
+ collection_name="instagram_posts",
+ persist_dir="./chroma_db"
+ )
+ print("✅ EmbeddingManager inicializado")
+
+ # Inicializa DashboardAnalytics
+ print("📊 Inicializando DashboardAnalytics...")
+ analytics = DashboardAnalytics(embedding_manager=em)
+ print("✅ DashboardAnalytics inicializado\n")
+
+ # Gera recomendações (vai testar o método completo)
+ print("🤖 Gerando recomendações de políticas...")
+ print(" (Isso pode levar alguns segundos...)\n")
+
+ result = analytics.generate_policy_recommendations(
+ profile_filter=None, # Todos os perfis
+ min_engagement=50,
+ top_n=3
+ )
+
+ print("\n📋 RESULTADO:")
+ print("-" * 60)
+
+ # Verifica se tem recomendações
+ if 'recommendations' in result:
+ recommendations = result['recommendations']
+ print(f"✅ Recomendações: {len(recommendations)} encontradas")
+ for i, rec in enumerate(recommendations, 1):
+ print(f"\n {i}. {rec.get('area', 'N/A')} (Prioridade: {rec.get('priority', 'N/A')})")
+ print(f" Ação: {rec.get('action', 'N/A')[:80]}...")
+ else:
+ print("❌ Não foram geradas recomendações")
+ return False
+
+ # VERIFICA ÁREAS CRÍTICAS (o foco deste teste)
+ print("\n" + "-" * 60)
+ if 'critical_areas' in result:
+ critical_areas = result['critical_areas']
+ if critical_areas and len(critical_areas) > 0:
+ print(f"✅ Áreas Críticas: {len(critical_areas)} identificadas\n")
+ for i, area in enumerate(critical_areas, 1):
+ print(f" {i}. {area.get('area', 'N/A')} (Frequência: {area.get('frequency', 'N/A')})")
+ examples = area.get('examples', [])
+ if examples:
+ print(f" Exemplos: {len(examples)}")
+ for j, ex in enumerate(examples[:2], 1):
+ print(f" {j}. {ex[:80]}...")
+ print()
+ else:
+ print("⚠️ Áreas Críticas: LISTA VAZIA (PROBLEMA!)")
+ print(" O LLM não retornou áreas críticas.")
+ return False
+ else:
+ print("❌ Áreas Críticas: CHAVE NÃO ENCONTRADA (PROBLEMA!)")
+ print(" O resultado não contém a chave 'critical_areas'")
+ return False
+
+ # Verifica aspectos positivos
+ print("-" * 60)
+ if 'positive_aspects' in result:
+ positive_aspects = result['positive_aspects']
+ if positive_aspects and len(positive_aspects) > 0:
+ print(f"✅ Aspectos Positivos: {len(positive_aspects)} encontrados\n")
+ for i, aspect in enumerate(positive_aspects, 1):
+ print(f" {i}. {aspect}")
+ else:
+ print("⚠️ Aspectos Positivos: lista vazia (ok, pode acontecer)")
+ else:
+ print("⚠️ Aspectos Positivos: chave não encontrada")
+
+ print("\n" + "="*60)
+ print("✅ TESTE PASSOU: Áreas críticas estão sendo geradas!")
+ print("="*60 + "\n")
+ return True
+
+ except Exception as e:
+ print("\n" + "="*60)
+ print(f"❌ ERRO NO TESTE: {e}")
+ print("="*60)
+ import traceback
+ traceback.print_exc()
+ return False
+
+
+if __name__ == '__main__':
+ success = test_critical_areas()
+ sys.exit(0 if success else 1)
diff --git a/test_export_with_critical_areas.py b/test_export_with_critical_areas.py
new file mode 100644
index 0000000..8c2db7f
--- /dev/null
+++ b/test_export_with_critical_areas.py
@@ -0,0 +1,154 @@
+#!/usr/bin/env python3
+"""
+Teste para verificar se a exportação de relatórios inclui as áreas críticas.
+"""
+
+import sys
+from analytics_dashboard import DashboardAnalytics
+from embedding_manager import EmbeddingManager
+from datetime import datetime
+from pathlib import Path
+
+
+def test_export_report():
+ """Testa se a exportação de relatórios inclui áreas críticas."""
+ print("\n" + "="*60)
+ print("📄 TESTE: Exportação de Relatório com Áreas Críticas")
+ print("="*60 + "\n")
+
+ try:
+ # Inicializa
+ print("📊 Inicializando sistema...")
+ em = EmbeddingManager(
+ collection_name="instagram_posts",
+ persist_dir="./chroma_db"
+ )
+ analytics = DashboardAnalytics(embedding_manager=em)
+ print("✅ Sistema inicializado\n")
+
+ # Gera recomendações PRIMEIRO (contém dados de sentimento)
+ print("🤖 Gerando recomendações de políticas...")
+ recommendations = analytics.generate_policy_recommendations(
+ profile_filter=None,
+ min_engagement=50,
+ top_n=3
+ )
+ print("✅ Recomendações geradas\n")
+
+ # Cria métricas básicas para o relatório
+ print("📦 Preparando dados para exportação...")
+ metrics = {
+ 'summary': {
+ 'total_records': em.collection.count(),
+ 'posts_count': em.collection.count() - 24, # aproximação
+ 'news_count': 24,
+ 'total_engagement': 150000,
+ 'avg_engagement_per_post': 62.5
+ },
+ 'posts': {
+ 'total': em.collection.count(),
+ 'total_likes': 120000,
+ 'total_comments': 30000,
+ 'avg_likes': 50.0,
+ 'avg_comments': 12.5,
+ 'by_profile': {},
+ 'top_by_engagement': []
+ },
+ 'sentiment': recommendations.get('sentiment_analysis', {}),
+ 'emerging_topics': {'total_topics': 0, 'topics': []},
+ 'news': {'total': 24, 'by_publisher': {}}
+ }
+ if recommendations.get('recommendations'):
+ sentiment_data = recommendations.get('sentiment_analysis', {})
+
+ export_format = {
+ 'has_recommendations': True,
+ 'generated_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
+ 'profile': "Todos os perfis",
+ 'content_filter': 'both',
+ 'sentiment_data': sentiment_data,
+ 'summary': f"Análise baseada em {len(recommendations.get('recommendations', []))} recomendações.",
+ 'critical_areas': recommendations.get('critical_areas', []),
+ 'recommendations': recommendations.get('recommendations', []),
+ 'positive_aspects': recommendations.get('positive_aspects', []),
+ 'general_observations': f"Sentimento: {sentiment_data.get('positive_pct', 0):.1f}% positivo"
+ }
+
+ metrics['policy_recommendations'] = export_format
+
+ print(f"✅ Dados preparados:")
+ print(f" - {len(export_format['recommendations'])} recomendações")
+ print(f" - {len(export_format['critical_areas'])} áreas críticas")
+ print(f" - {len(export_format['positive_aspects'])} aspectos positivos\n")
+
+ # Exporta CSV
+ print("📄 Exportando relatório CSV...")
+ csv_content = analytics.export_report(metrics, 'csv', 'test_relatorio_areas_criticas.csv')
+
+ csv_path = Path('./exports/test_relatorio_areas_criticas.csv')
+ csv_path.parent.mkdir(exist_ok=True)
+ csv_path.write_text(csv_content, encoding='utf-8')
+ print(f"✅ CSV exportado: {csv_path}\n")
+
+ # Verifica se o CSV contém as áreas críticas
+ print("🔍 Verificando conteúdo do CSV...")
+ if 'ÁREAS PROBLEMÁTICAS IDENTIFICADAS' in csv_content:
+ print("✅ Seção 'ÁREAS PROBLEMÁTICAS IDENTIFICADAS' encontrada!")
+
+ # Conta quantas áreas foram incluídas
+ lines = csv_content.split('\n')
+ areas_section_found = False
+ areas_count = 0
+
+ for line in lines:
+ if 'ÁREAS PROBLEMÁTICAS IDENTIFICADAS' in line:
+ areas_section_found = True
+ continue
+
+ if areas_section_found:
+ if line.startswith('===') or line.startswith('RECOMENDAÇÕES'):
+ break
+ if line.strip() and not line.startswith('Área,'):
+ areas_count += 1
+
+ print(f" Áreas exportadas no CSV: {areas_count}")
+
+ if areas_count > 0:
+ print("✅ ÁREAS CRÍTICAS EXPORTADAS COM SUCESSO NO CSV!")
+ else:
+ print("⚠️ Seção encontrada mas está vazia no CSV")
+ else:
+ print("❌ Seção 'ÁREAS PROBLEMÁTICAS IDENTIFICADAS' NÃO encontrada no CSV")
+
+ # Exporta PDF
+ print("\n📕 Exportando relatório PDF...")
+ pdf_bytes = analytics.export_report(metrics, 'pdf', 'test_relatorio_areas_criticas.pdf')
+
+ pdf_path = Path('./exports/test_relatorio_areas_criticas.pdf')
+ pdf_path.write_bytes(pdf_bytes)
+ print(f"✅ PDF exportado: {pdf_path}")
+ print(f" Tamanho: {len(pdf_bytes):,} bytes\n")
+
+ print("="*60)
+ print("✅ TESTE COMPLETO: Relatórios gerados com áreas críticas!")
+ print("="*60)
+ print(f"\nArquivos gerados:")
+ print(f" - {csv_path}")
+ print(f" - {pdf_path}")
+ print("\n✨ Abra os arquivos para verificar se as áreas críticas")
+ print(" estão sendo exibidas corretamente!\n")
+
+ return True
+
+ except Exception as e:
+ print("\n" + "="*60)
+ print(f"❌ ERRO NO TESTE: {e}")
+ print("="*60)
+ import traceback
+ traceback.print_exc()
+ return False
+
+
+if __name__ == '__main__':
+ success = test_export_report()
+ sys.exit(0 if success else 1)
diff --git a/test_nltk_stopwords.py b/test_nltk_stopwords.py
new file mode 100644
index 0000000..48295c2
--- /dev/null
+++ b/test_nltk_stopwords.py
@@ -0,0 +1,42 @@
+"""
+Teste para verificar a integração com NLTK stopwords.
+"""
+
+import nltk
+from nltk.corpus import stopwords
+
+# Download stopwords (se necessário)
+try:
+ stopwords.words('portuguese')
+ print("✅ Stopwords já disponíveis")
+except LookupError:
+ print("⬇️ Baixando stopwords do NLTK...")
+ nltk.download('stopwords', quiet=True)
+ print("✅ Stopwords baixadas com sucesso!")
+
+# Teste básico
+print("\n📊 Estatísticas de Stopwords:")
+print(f" - Total de stopwords (português): {len(stopwords.words('portuguese'))}")
+print(f" - Exemplos: {stopwords.words('portuguese')[:15]}")
+
+# Teste com stopwords customizadas
+nltk_stopwords = set(stopwords.words('portuguese'))
+technical_terms = {'https', 'http', 'www', 'com', 'br', 'instagram', 'post', 'foto'}
+stopwords_combined = nltk_stopwords.union(technical_terms)
+
+print(f"\n✨ Stopwords combinadas (NLTK + termos técnicos):")
+print(f" - Total: {len(stopwords_combined)} palavras")
+print(f" - Termos técnicos adicionados: {technical_terms}")
+
+# Teste de filtragem
+test_text = "A UFF é uma universidade federal do Brasil que está no Instagram com fotos e posts"
+words = test_text.lower().split()
+filtered_words = [w for w in words if w not in stopwords_combined and len(w) >= 4]
+
+print(f"\n🧪 Teste de filtragem:")
+print(f" - Texto original: {test_text}")
+print(f" - Palavras originais: {words}")
+print(f" - Palavras filtradas: {filtered_words}")
+print(f" - Removidas: {len(words) - len(filtered_words)} palavras")
+
+print("\n✅ Teste concluído com sucesso!")
diff --git a/uv.lock b/uv.lock
index 8b26f2e..e98ac91 100644
--- a/uv.lock
+++ b/uv.lock
@@ -1195,6 +1195,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/d9/71/71408b02c6133153336d29fa3ba53000f1e1a3f78bb2fc2d1a1865d2e743/jiter-0.11.1-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18c77aaa9117510d5bdc6a946baf21b1f0cfa58ef04d31c8d016f206f2118960", size = 343697, upload-time = "2025-10-17T11:31:13.773Z" },
]
+[[package]]
+name = "joblib"
+version = "1.5.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/e8/5d/447af5ea094b9e4c4054f82e223ada074c552335b9b4b2d14bd9b35a67c4/joblib-1.5.2.tar.gz", hash = "sha256:3faa5c39054b2f03ca547da9b2f52fde67c06240c31853f306aea97f13647b55", size = 331077, upload-time = "2025-08-27T12:15:46.575Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1e/e8/685f47e0d754320684db4425a0967f7d3fa70126bffd76110b7009a0090f/joblib-1.5.2-py3-none-any.whl", hash = "sha256:4e1f0bdbb987e6d843c70cf43714cb276623def372df3c22fe5266b2670bc241", size = 308396, upload-time = "2025-08-27T12:15:45.188Z" },
+]
+
[[package]]
name = "jsonpatch"
version = "1.33"
@@ -1726,6 +1735,21 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" },
]
+[[package]]
+name = "nltk"
+version = "3.9.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "click" },
+ { name = "joblib" },
+ { name = "regex" },
+ { name = "tqdm" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/f9/76/3a5e4312c19a028770f86fd7c058cf9f4ec4321c6cf7526bab998a5b683c/nltk-3.9.2.tar.gz", hash = "sha256:0f409e9b069ca4177c1903c3e843eef90c7e92992fa4931ae607da6de49e1419", size = 2887629, upload-time = "2025-10-01T07:19:23.764Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/60/90/81ac364ef94209c100e12579629dc92bf7a709a84af32f8c551b02c07e94/nltk-3.9.2-py3-none-any.whl", hash = "sha256:1e209d2b3009110635ed9709a67a1a3e33a10f799490fa71cf4bec218c11c88a", size = 1513404, upload-time = "2025-10-01T07:19:21.648Z" },
+]
+
[[package]]
name = "numpy"
version = "2.3.4"
@@ -2130,9 +2154,12 @@ dependencies = [
{ name = "gradio" },
{ name = "langchain" },
{ name = "langchain-community" },
+ { name = "nltk" },
{ name = "ollama" },
{ name = "openai" },
+ { name = "pypdf2" },
{ name = "python-dateutil" },
+ { name = "reportlab" },
]
[package.metadata]
@@ -2143,9 +2170,12 @@ requires-dist = [
{ name = "gradio", specifier = ">=4.0.0" },
{ name = "langchain", specifier = ">=0.1.0" },
{ name = "langchain-community", specifier = ">=0.0.10" },
+ { name = "nltk", specifier = ">=3.8.0" },
{ name = "ollama", specifier = ">=0.1.0" },
{ name = "openai", specifier = ">=1.0.0" },
+ { name = "pypdf2", specifier = ">=3.0.0" },
{ name = "python-dateutil", specifier = ">=2.8.0" },
+ { name = "reportlab", specifier = ">=4.4.4" },
]
[[package]]
@@ -2509,6 +2539,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" },
]
+[[package]]
+name = "pypdf2"
+version = "3.0.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/9f/bb/18dc3062d37db6c491392007dfd1a7f524bb95886eb956569ac38a23a784/PyPDF2-3.0.1.tar.gz", hash = "sha256:a74408f69ba6271f71b9352ef4ed03dc53a31aa404d29b5d31f53bfecfee1440", size = 227419, upload-time = "2022-12-31T10:36:13.13Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/8e/5e/c86a5643653825d3c913719e788e41386bee415c2b87b4f955432f2de6b2/pypdf2-3.0.1-py3-none-any.whl", hash = "sha256:d16e4205cfee272fbdc0568b68d82be796540b1537508cef59388f839c191928", size = 232572, upload-time = "2022-12-31T10:36:10.327Z" },
+]
+
[[package]]
name = "pypika"
version = "0.48.9"
@@ -2632,6 +2671,97 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" },
]
+[[package]]
+name = "regex"
+version = "2025.10.23"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f8/c8/1d2160d36b11fbe0a61acb7c3c81ab032d9ec8ad888ac9e0a61b85ab99dd/regex-2025.10.23.tar.gz", hash = "sha256:8cbaf8ceb88f96ae2356d01b9adf5e6306fa42fa6f7eab6b97794e37c959ac26", size = 401266, upload-time = "2025-10-21T15:58:20.23Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/f6/57/eeb274d83ab189d02d778851b1ac478477522a92b52edfa6e2ae9ff84679/regex-2025.10.23-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:7a44d9c00f7a0a02d3b777429281376370f3d13d2c75ae74eb94e11ebcf4a7fc", size = 489187, upload-time = "2025-10-21T15:55:18.322Z" },
+ { url = "https://files.pythonhosted.org/packages/55/5c/7dad43a9b6ea88bf77e0b8b7729a4c36978e1043165034212fd2702880c6/regex-2025.10.23-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b83601f84fde939ae3478bb32a3aef36f61b58c3208d825c7e8ce1a735f143f2", size = 291122, upload-time = "2025-10-21T15:55:20.2Z" },
+ { url = "https://files.pythonhosted.org/packages/66/21/38b71e6f2818f0f4b281c8fba8d9d57cfca7b032a648fa59696e0a54376a/regex-2025.10.23-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ec13647907bb9d15fd192bbfe89ff06612e098a5709e7d6ecabbdd8f7908fc45", size = 288797, upload-time = "2025-10-21T15:55:21.932Z" },
+ { url = "https://files.pythonhosted.org/packages/be/95/888f069c89e7729732a6d7cca37f76b44bfb53a1e35dda8a2c7b65c1b992/regex-2025.10.23-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:78d76dd2957d62501084e7012ddafc5fcd406dd982b7a9ca1ea76e8eaaf73e7e", size = 798442, upload-time = "2025-10-21T15:55:23.747Z" },
+ { url = "https://files.pythonhosted.org/packages/76/70/4f903c608faf786627a8ee17c06e0067b5acade473678b69c8094b248705/regex-2025.10.23-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8668e5f067e31a47699ebb354f43aeb9c0ef136f915bd864243098524482ac43", size = 864039, upload-time = "2025-10-21T15:55:25.656Z" },
+ { url = "https://files.pythonhosted.org/packages/62/19/2df67b526bf25756c7f447dde554fc10a220fd839cc642f50857d01e4a7b/regex-2025.10.23-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a32433fe3deb4b2d8eda88790d2808fed0dc097e84f5e683b4cd4f42edef6cca", size = 912057, upload-time = "2025-10-21T15:55:27.309Z" },
+ { url = "https://files.pythonhosted.org/packages/99/14/9a39b7c9e007968411bc3c843cc14cf15437510c0a9991f080cab654fd16/regex-2025.10.23-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d97d73818c642c938db14c0668167f8d39520ca9d983604575ade3fda193afcc", size = 803374, upload-time = "2025-10-21T15:55:28.9Z" },
+ { url = "https://files.pythonhosted.org/packages/d4/f7/3495151dd3ca79949599b6d069b72a61a2c5e24fc441dccc79dcaf708fe6/regex-2025.10.23-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bca7feecc72ee33579e9f6ddf8babbe473045717a0e7dbc347099530f96e8b9a", size = 787714, upload-time = "2025-10-21T15:55:30.628Z" },
+ { url = "https://files.pythonhosted.org/packages/28/65/ee882455e051131869957ee8597faea45188c9a98c0dad724cfb302d4580/regex-2025.10.23-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7e24af51e907d7457cc4a72691ec458320b9ae67dc492f63209f01eecb09de32", size = 858392, upload-time = "2025-10-21T15:55:32.322Z" },
+ { url = "https://files.pythonhosted.org/packages/53/25/9287fef5be97529ebd3ac79d256159cb709a07eb58d4be780d1ca3885da8/regex-2025.10.23-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d10bcde58bbdf18146f3a69ec46dd03233b94a4a5632af97aa5378da3a47d288", size = 850484, upload-time = "2025-10-21T15:55:34.037Z" },
+ { url = "https://files.pythonhosted.org/packages/f3/b4/b49b88b4fea2f14dc73e5b5842755e782fc2e52f74423d6f4adc130d5880/regex-2025.10.23-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:44383bc0c933388516c2692c9a7503e1f4a67e982f20b9a29d2fb70c6494f147", size = 789634, upload-time = "2025-10-21T15:55:35.958Z" },
+ { url = "https://files.pythonhosted.org/packages/b6/3c/2f8d199d0e84e78bcd6bdc2be9b62410624f6b796e2893d1837ae738b160/regex-2025.10.23-cp312-cp312-win32.whl", hash = "sha256:6040a86f95438a0114bba16e51dfe27f1bc004fd29fe725f54a586f6d522b079", size = 266060, upload-time = "2025-10-21T15:55:37.902Z" },
+ { url = "https://files.pythonhosted.org/packages/d7/67/c35e80969f6ded306ad70b0698863310bdf36aca57ad792f45ddc0e2271f/regex-2025.10.23-cp312-cp312-win_amd64.whl", hash = "sha256:436b4c4352fe0762e3bfa34a5567079baa2ef22aa9c37cf4d128979ccfcad842", size = 276931, upload-time = "2025-10-21T15:55:39.502Z" },
+ { url = "https://files.pythonhosted.org/packages/f5/a1/4ed147de7d2b60174f758412c87fa51ada15cd3296a0ff047f4280aaa7ca/regex-2025.10.23-cp312-cp312-win_arm64.whl", hash = "sha256:f4b1b1991617055b46aff6f6db24888c1f05f4db9801349d23f09ed0714a9335", size = 270103, upload-time = "2025-10-21T15:55:41.24Z" },
+ { url = "https://files.pythonhosted.org/packages/28/c6/195a6217a43719d5a6a12cc192a22d12c40290cecfa577f00f4fb822f07d/regex-2025.10.23-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:b7690f95404a1293923a296981fd943cca12c31a41af9c21ba3edd06398fc193", size = 488956, upload-time = "2025-10-21T15:55:42.887Z" },
+ { url = "https://files.pythonhosted.org/packages/4c/93/181070cd1aa2fa541ff2d3afcf763ceecd4937b34c615fa92765020a6c90/regex-2025.10.23-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1a32d77aeaea58a13230100dd8797ac1a84c457f3af2fdf0d81ea689d5a9105b", size = 290997, upload-time = "2025-10-21T15:55:44.53Z" },
+ { url = "https://files.pythonhosted.org/packages/b6/c5/9d37fbe3a40ed8dda78c23e1263002497540c0d1522ed75482ef6c2000f0/regex-2025.10.23-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b24b29402f264f70a3c81f45974323b41764ff7159655360543b7cabb73e7d2f", size = 288686, upload-time = "2025-10-21T15:55:46.186Z" },
+ { url = "https://files.pythonhosted.org/packages/5f/e7/db610ff9f10c2921f9b6ac0c8d8be4681b28ddd40fc0549429366967e61f/regex-2025.10.23-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:563824a08c7c03d96856d84b46fdb3bbb7cfbdf79da7ef68725cda2ce169c72a", size = 798466, upload-time = "2025-10-21T15:55:48.24Z" },
+ { url = "https://files.pythonhosted.org/packages/90/10/aab883e1fa7fe2feb15ac663026e70ca0ae1411efa0c7a4a0342d9545015/regex-2025.10.23-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a0ec8bdd88d2e2659c3518087ee34b37e20bd169419ffead4240a7004e8ed03b", size = 863996, upload-time = "2025-10-21T15:55:50.478Z" },
+ { url = "https://files.pythonhosted.org/packages/a2/b0/8f686dd97a51f3b37d0238cd00a6d0f9ccabe701f05b56de1918571d0d61/regex-2025.10.23-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b577601bfe1d33913fcd9276d7607bbac827c4798d9e14d04bf37d417a6c41cb", size = 912145, upload-time = "2025-10-21T15:55:52.215Z" },
+ { url = "https://files.pythonhosted.org/packages/a3/ca/639f8cd5b08797bca38fc5e7e07f76641a428cf8c7fca05894caf045aa32/regex-2025.10.23-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c9f2c68ac6cb3de94eea08a437a75eaa2bd33f9e97c84836ca0b610a5804368", size = 803370, upload-time = "2025-10-21T15:55:53.944Z" },
+ { url = "https://files.pythonhosted.org/packages/0d/1e/a40725bb76959eddf8abc42a967bed6f4851b39f5ac4f20e9794d7832aa5/regex-2025.10.23-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:89f8b9ea3830c79468e26b0e21c3585f69f105157c2154a36f6b7839f8afb351", size = 787767, upload-time = "2025-10-21T15:55:56.004Z" },
+ { url = "https://files.pythonhosted.org/packages/3d/d8/8ee9858062936b0f99656dce390aa667c6e7fb0c357b1b9bf76fb5e2e708/regex-2025.10.23-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:98fd84c4e4ea185b3bb5bf065261ab45867d8875032f358a435647285c722673", size = 858335, upload-time = "2025-10-21T15:55:58.185Z" },
+ { url = "https://files.pythonhosted.org/packages/d8/0a/ed5faaa63fa8e3064ab670e08061fbf09e3a10235b19630cf0cbb9e48c0a/regex-2025.10.23-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:1e11d3e5887b8b096f96b4154dfb902f29c723a9556639586cd140e77e28b313", size = 850402, upload-time = "2025-10-21T15:56:00.023Z" },
+ { url = "https://files.pythonhosted.org/packages/79/14/d05f617342f4b2b4a23561da500ca2beab062bfcc408d60680e77ecaf04d/regex-2025.10.23-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f13450328a6634348d47a88367e06b64c9d84980ef6a748f717b13f8ce64e87", size = 789739, upload-time = "2025-10-21T15:56:01.967Z" },
+ { url = "https://files.pythonhosted.org/packages/f9/7b/e8ce8eef42a15f2c3461f8b3e6e924bbc86e9605cb534a393aadc8d3aff8/regex-2025.10.23-cp313-cp313-win32.whl", hash = "sha256:37be9296598a30c6a20236248cb8b2c07ffd54d095b75d3a2a2ee5babdc51df1", size = 266054, upload-time = "2025-10-21T15:56:05.291Z" },
+ { url = "https://files.pythonhosted.org/packages/71/2d/55184ed6be6473187868d2f2e6a0708195fc58270e62a22cbf26028f2570/regex-2025.10.23-cp313-cp313-win_amd64.whl", hash = "sha256:ea7a3c283ce0f06fe789365841e9174ba05f8db16e2fd6ae00a02df9572c04c0", size = 276917, upload-time = "2025-10-21T15:56:07.303Z" },
+ { url = "https://files.pythonhosted.org/packages/9c/d4/927eced0e2bd45c45839e556f987f8c8f8683268dd3c00ad327deb3b0172/regex-2025.10.23-cp313-cp313-win_arm64.whl", hash = "sha256:d9a4953575f300a7bab71afa4cd4ac061c7697c89590a2902b536783eeb49a4f", size = 270105, upload-time = "2025-10-21T15:56:09.857Z" },
+ { url = "https://files.pythonhosted.org/packages/3e/b3/95b310605285573341fc062d1d30b19a54f857530e86c805f942c4ff7941/regex-2025.10.23-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:7d6606524fa77b3912c9ef52a42ef63c6cfbfc1077e9dc6296cd5da0da286044", size = 491850, upload-time = "2025-10-21T15:56:11.685Z" },
+ { url = "https://files.pythonhosted.org/packages/a4/8f/207c2cec01e34e56db1eff606eef46644a60cf1739ecd474627db90ad90b/regex-2025.10.23-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c037aadf4d64bdc38af7db3dbd34877a057ce6524eefcb2914d6d41c56f968cc", size = 292537, upload-time = "2025-10-21T15:56:13.963Z" },
+ { url = "https://files.pythonhosted.org/packages/98/3b/025240af4ada1dc0b5f10d73f3e5122d04ce7f8908ab8881e5d82b9d61b6/regex-2025.10.23-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:99018c331fb2529084a0c9b4c713dfa49fafb47c7712422e49467c13a636c656", size = 290904, upload-time = "2025-10-21T15:56:16.016Z" },
+ { url = "https://files.pythonhosted.org/packages/81/8e/104ac14e2d3450c43db18ec03e1b96b445a94ae510b60138f00ce2cb7ca1/regex-2025.10.23-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fd8aba965604d70306eb90a35528f776e59112a7114a5162824d43b76fa27f58", size = 807311, upload-time = "2025-10-21T15:56:17.818Z" },
+ { url = "https://files.pythonhosted.org/packages/19/63/78aef90141b7ce0be8a18e1782f764f6997ad09de0e05251f0d2503a914a/regex-2025.10.23-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:238e67264b4013e74136c49f883734f68656adf8257bfa13b515626b31b20f8e", size = 873241, upload-time = "2025-10-21T15:56:19.941Z" },
+ { url = "https://files.pythonhosted.org/packages/b3/a8/80eb1201bb49ae4dba68a1b284b4211ed9daa8e74dc600018a10a90399fb/regex-2025.10.23-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b2eb48bd9848d66fd04826382f5e8491ae633de3233a3d64d58ceb4ecfa2113a", size = 914794, upload-time = "2025-10-21T15:56:22.488Z" },
+ { url = "https://files.pythonhosted.org/packages/f0/d5/1984b6ee93281f360a119a5ca1af6a8ca7d8417861671388bf750becc29b/regex-2025.10.23-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d36591ce06d047d0c0fe2fc5f14bfbd5b4525d08a7b6a279379085e13f0e3d0e", size = 812581, upload-time = "2025-10-21T15:56:24.319Z" },
+ { url = "https://files.pythonhosted.org/packages/c4/39/11ebdc6d9927172a64ae237d16763145db6bd45ebb4055c17b88edab72a7/regex-2025.10.23-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b5d4ece8628d6e364302006366cea3ee887db397faebacc5dacf8ef19e064cf8", size = 795346, upload-time = "2025-10-21T15:56:26.232Z" },
+ { url = "https://files.pythonhosted.org/packages/3b/b4/89a591bcc08b5e436af43315284bd233ba77daf0cf20e098d7af12f006c1/regex-2025.10.23-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:39a7e8083959cb1c4ff74e483eecb5a65d3b3e1d821b256e54baf61782c906c6", size = 868214, upload-time = "2025-10-21T15:56:28.597Z" },
+ { url = "https://files.pythonhosted.org/packages/3d/ff/58ba98409c1dbc8316cdb20dafbc63ed267380a07780cafecaf5012dabc9/regex-2025.10.23-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:842d449a8fefe546f311656cf8c0d6729b08c09a185f1cad94c756210286d6a8", size = 854540, upload-time = "2025-10-21T15:56:30.875Z" },
+ { url = "https://files.pythonhosted.org/packages/9a/f2/4a9e9338d67626e2071b643f828a482712ad15889d7268e11e9a63d6f7e9/regex-2025.10.23-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d614986dc68506be8f00474f4f6960e03e4ca9883f7df47744800e7d7c08a494", size = 799346, upload-time = "2025-10-21T15:56:32.725Z" },
+ { url = "https://files.pythonhosted.org/packages/63/be/543d35c46bebf6f7bf2be538cca74d6585f25714700c36f37f01b92df551/regex-2025.10.23-cp313-cp313t-win32.whl", hash = "sha256:a5b7a26b51a9df473ec16a1934d117443a775ceb7b39b78670b2e21893c330c9", size = 268657, upload-time = "2025-10-21T15:56:34.577Z" },
+ { url = "https://files.pythonhosted.org/packages/14/9f/4dd6b7b612037158bb2c9bcaa710e6fb3c40ad54af441b9c53b3a137a9f1/regex-2025.10.23-cp313-cp313t-win_amd64.whl", hash = "sha256:ce81c5544a5453f61cb6f548ed358cfb111e3b23f3cd42d250a4077a6be2a7b6", size = 280075, upload-time = "2025-10-21T15:56:36.767Z" },
+ { url = "https://files.pythonhosted.org/packages/81/7a/5bd0672aa65d38c8da6747c17c8b441bdb53d816c569e3261013af8e83cf/regex-2025.10.23-cp313-cp313t-win_arm64.whl", hash = "sha256:e9bf7f6699f490e4e43c44757aa179dab24d1960999c84ab5c3d5377714ed473", size = 271219, upload-time = "2025-10-21T15:56:39.033Z" },
+ { url = "https://files.pythonhosted.org/packages/73/f6/0caf29fec943f201fbc8822879c99d31e59c1d51a983d9843ee5cf398539/regex-2025.10.23-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:5b5cb5b6344c4c4c24b2dc87b0bfee78202b07ef7633385df70da7fcf6f7cec6", size = 488960, upload-time = "2025-10-21T15:56:40.849Z" },
+ { url = "https://files.pythonhosted.org/packages/8e/7d/ebb7085b8fa31c24ce0355107cea2b92229d9050552a01c5d291c42aecea/regex-2025.10.23-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:a6ce7973384c37bdf0f371a843f95a6e6f4e1489e10e0cf57330198df72959c5", size = 290932, upload-time = "2025-10-21T15:56:42.875Z" },
+ { url = "https://files.pythonhosted.org/packages/27/41/43906867287cbb5ca4cee671c3cc8081e15deef86a8189c3aad9ac9f6b4d/regex-2025.10.23-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2ee3663f2c334959016b56e3bd0dd187cbc73f948e3a3af14c3caaa0c3035d10", size = 288766, upload-time = "2025-10-21T15:56:44.894Z" },
+ { url = "https://files.pythonhosted.org/packages/ab/9e/ea66132776700fc77a39b1056e7a5f1308032fead94507e208dc6716b7cd/regex-2025.10.23-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2003cc82a579107e70d013482acce8ba773293f2db534fb532738395c557ff34", size = 798884, upload-time = "2025-10-21T15:56:47.178Z" },
+ { url = "https://files.pythonhosted.org/packages/d5/99/aed1453687ab63819a443930770db972c5c8064421f0d9f5da9ad029f26b/regex-2025.10.23-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:182c452279365a93a9f45874f7f191ec1c51e1f1eb41bf2b16563f1a40c1da3a", size = 864768, upload-time = "2025-10-21T15:56:49.793Z" },
+ { url = "https://files.pythonhosted.org/packages/99/5d/732fe747a1304805eb3853ce6337eea16b169f7105a0d0dd9c6a5ffa9948/regex-2025.10.23-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b1249e9ff581c5b658c8f0437f883b01f1edcf424a16388591e7c05e5e9e8b0c", size = 911394, upload-time = "2025-10-21T15:56:52.186Z" },
+ { url = "https://files.pythonhosted.org/packages/5e/48/58a1f6623466522352a6efa153b9a3714fc559d9f930e9bc947b4a88a2c3/regex-2025.10.23-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b841698f93db3ccc36caa1900d2a3be281d9539b822dc012f08fc80b46a3224", size = 803145, upload-time = "2025-10-21T15:56:55.142Z" },
+ { url = "https://files.pythonhosted.org/packages/ea/f6/7dea79be2681a5574ab3fc237aa53b2c1dfd6bd2b44d4640b6c76f33f4c1/regex-2025.10.23-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:956d89e0c92d471e8f7eee73f73fdff5ed345886378c45a43175a77538a1ffe4", size = 787831, upload-time = "2025-10-21T15:56:57.203Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/ad/07b76950fbbe65f88120ca2d8d845047c401450f607c99ed38862904671d/regex-2025.10.23-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5c259cb363299a0d90d63b5c0d7568ee98419861618a95ee9d91a41cb9954462", size = 859162, upload-time = "2025-10-21T15:56:59.195Z" },
+ { url = "https://files.pythonhosted.org/packages/41/87/374f3b2021b22aa6a4fc0b750d63f9721e53d1631a238f7a1c343c1cd288/regex-2025.10.23-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:185d2b18c062820b3a40d8fefa223a83f10b20a674bf6e8c4a432e8dfd844627", size = 849899, upload-time = "2025-10-21T15:57:01.747Z" },
+ { url = "https://files.pythonhosted.org/packages/12/4a/7f7bb17c5a5a9747249807210e348450dab9212a46ae6d23ebce86ba6a2b/regex-2025.10.23-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:281d87fa790049c2b7c1b4253121edd80b392b19b5a3d28dc2a77579cb2a58ec", size = 789372, upload-time = "2025-10-21T15:57:04.018Z" },
+ { url = "https://files.pythonhosted.org/packages/c9/dd/9c7728ff544fea09bbc8635e4c9e7c423b11c24f1a7a14e6ac4831466709/regex-2025.10.23-cp314-cp314-win32.whl", hash = "sha256:63b81eef3656072e4ca87c58084c7a9c2b81d41a300b157be635a8a675aacfb8", size = 271451, upload-time = "2025-10-21T15:57:06.266Z" },
+ { url = "https://files.pythonhosted.org/packages/48/f8/ef7837ff858eb74079c4804c10b0403c0b740762e6eedba41062225f7117/regex-2025.10.23-cp314-cp314-win_amd64.whl", hash = "sha256:0967c5b86f274800a34a4ed862dfab56928144d03cb18821c5153f8777947796", size = 280173, upload-time = "2025-10-21T15:57:08.206Z" },
+ { url = "https://files.pythonhosted.org/packages/8e/d0/d576e1dbd9885bfcd83d0e90762beea48d9373a6f7ed39170f44ed22e336/regex-2025.10.23-cp314-cp314-win_arm64.whl", hash = "sha256:c70dfe58b0a00b36aa04cdb0f798bf3e0adc31747641f69e191109fd8572c9a9", size = 273206, upload-time = "2025-10-21T15:57:10.367Z" },
+ { url = "https://files.pythonhosted.org/packages/a6/d0/2025268315e8b2b7b660039824cb7765a41623e97d4cd421510925400487/regex-2025.10.23-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:1f5799ea1787aa6de6c150377d11afad39a38afd033f0c5247aecb997978c422", size = 491854, upload-time = "2025-10-21T15:57:12.526Z" },
+ { url = "https://files.pythonhosted.org/packages/44/35/5681c2fec5e8b33454390af209c4353dfc44606bf06d714b0b8bd0454ffe/regex-2025.10.23-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:a9639ab7540cfea45ef57d16dcbea2e22de351998d614c3ad2f9778fa3bdd788", size = 292542, upload-time = "2025-10-21T15:57:15.158Z" },
+ { url = "https://files.pythonhosted.org/packages/5d/17/184eed05543b724132e4a18149e900f5189001fcfe2d64edaae4fbaf36b4/regex-2025.10.23-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:08f52122c352eb44c3421dab78b9b73a8a77a282cc8314ae576fcaa92b780d10", size = 290903, upload-time = "2025-10-21T15:57:17.108Z" },
+ { url = "https://files.pythonhosted.org/packages/25/d0/5e3347aa0db0de382dddfa133a7b0ae72f24b4344f3989398980b44a3924/regex-2025.10.23-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ebf1baebef1c4088ad5a5623decec6b52950f0e4d7a0ae4d48f0a99f8c9cb7d7", size = 807546, upload-time = "2025-10-21T15:57:19.179Z" },
+ { url = "https://files.pythonhosted.org/packages/d2/bb/40c589bbdce1be0c55e9f8159789d58d47a22014f2f820cf2b517a5cd193/regex-2025.10.23-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:16b0f1c2e2d566c562d5c384c2b492646be0a19798532fdc1fdedacc66e3223f", size = 873322, upload-time = "2025-10-21T15:57:21.36Z" },
+ { url = "https://files.pythonhosted.org/packages/fe/56/a7e40c01575ac93360e606278d359f91829781a9f7fb6e5aa435039edbda/regex-2025.10.23-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f7ada5d9dceafaab92646aa00c10a9efd9b09942dd9b0d7c5a4b73db92cc7e61", size = 914855, upload-time = "2025-10-21T15:57:24.044Z" },
+ { url = "https://files.pythonhosted.org/packages/5c/4b/d55587b192763db3163c3f508b3b67b31bb6f5e7a0e08b83013d0a59500a/regex-2025.10.23-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3a36b4005770044bf08edecc798f0e41a75795b9e7c9c12fe29da8d792ef870c", size = 812724, upload-time = "2025-10-21T15:57:26.123Z" },
+ { url = "https://files.pythonhosted.org/packages/33/20/18bac334955fbe99d17229f4f8e98d05e4a501ac03a442be8facbb37c304/regex-2025.10.23-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:af7b2661dcc032da1fae82069b5ebf2ac1dfcd5359ef8b35e1367bfc92181432", size = 795439, upload-time = "2025-10-21T15:57:28.497Z" },
+ { url = "https://files.pythonhosted.org/packages/67/46/c57266be9df8549c7d85deb4cb82280cb0019e46fff677534c5fa1badfa4/regex-2025.10.23-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:1cb976810ac1416a67562c2e5ba0accf6f928932320fef302e08100ed681b38e", size = 868336, upload-time = "2025-10-21T15:57:30.867Z" },
+ { url = "https://files.pythonhosted.org/packages/b8/f3/bd5879e41ef8187fec5e678e94b526a93f99e7bbe0437b0f2b47f9101694/regex-2025.10.23-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:1a56a54be3897d62f54290190fbcd754bff6932934529fbf5b29933da28fcd43", size = 854567, upload-time = "2025-10-21T15:57:33.062Z" },
+ { url = "https://files.pythonhosted.org/packages/e6/57/2b6bbdbd2f24dfed5b028033aa17ad8f7d86bb28f1a892cac8b3bc89d059/regex-2025.10.23-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8f3e6d202fb52c2153f532043bbcf618fd177df47b0b306741eb9b60ba96edc3", size = 799565, upload-time = "2025-10-21T15:57:35.153Z" },
+ { url = "https://files.pythonhosted.org/packages/c7/ba/a6168f542ba73b151ed81237adf6b869c7b2f7f8d51618111296674e20ee/regex-2025.10.23-cp314-cp314t-win32.whl", hash = "sha256:1fa1186966b2621b1769fd467c7b22e317e6ba2d2cdcecc42ea3089ef04a8521", size = 274428, upload-time = "2025-10-21T15:57:37.996Z" },
+ { url = "https://files.pythonhosted.org/packages/ef/a0/c84475e14a2829e9b0864ebf77c3f7da909df9d8acfe2bb540ff0072047c/regex-2025.10.23-cp314-cp314t-win_amd64.whl", hash = "sha256:08a15d40ce28362eac3e78e83d75475147869c1ff86bc93285f43b4f4431a741", size = 284140, upload-time = "2025-10-21T15:57:40.027Z" },
+ { url = "https://files.pythonhosted.org/packages/51/33/6a08ade0eee5b8ba79386869fa6f77afeb835b60510f3525db987e2fffc4/regex-2025.10.23-cp314-cp314t-win_arm64.whl", hash = "sha256:a93e97338e1c8ea2649e130dcfbe8cd69bba5e1e163834752ab64dcb4de6d5ed", size = 274497, upload-time = "2025-10-21T15:57:42.389Z" },
+]
+
+[[package]]
+name = "reportlab"
+version = "4.4.4"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "charset-normalizer" },
+ { name = "pillow" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/f8/fa/ed71f3e750afb77497641eb0194aeda069e271ce6d6931140f8787e0e69a/reportlab-4.4.4.tar.gz", hash = "sha256:cb2f658b7f4a15be2cc68f7203aa67faef67213edd4f2d4bdd3eb20dab75a80d", size = 3711935, upload-time = "2025-09-19T10:43:36.502Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/57/66/e040586fe6f9ae7f3a6986186653791fb865947f0b745290ee4ab026b834/reportlab-4.4.4-py3-none-any.whl", hash = "sha256:299b3b0534e7202bb94ed2ddcd7179b818dcda7de9d8518a57c85a58a1ebaadb", size = 1954981, upload-time = "2025-09-19T10:43:33.589Z" },
+]
+
[[package]]
name = "requests"
version = "2.32.5"