# ===================================================================
# SETUP
# ===================================================================
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.2     ✔ tibble    3.3.0
## ✔ lubridate 1.9.4     ✔ tidyr     1.3.1
## ✔ purrr     1.1.0     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(here)
## here() starts at C:/Users/Rafael/OneDrive/CAPES Quadrienal 2025
library(glue)

# ===================================================================
# LOAD DATA 
# ===================================================================

spine <- read_csv(here("data", "planilhao", "spine.csv"))
## Rows: 547 Columns: 22
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (15): Cod PPG, Nome PPG, IES Principal Sigla, IES Principal Nome, IES da...
## dbl  (7): Ano base, PPG Ano Início, DPs, Colaboradores, Visitantes, Disserta...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
output <- read_csv(here("data", "planilhao", "producao_detalhada.csv"))
## Rows: 113940 Columns: 19
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr  (8): Cod PPG, Titulo da Produção, Tipo, Subtipo, Estrato, ISSN_ISBN, So...
## dbl (11): Ano base, Permanente, Colaborador, Visitante, Total de Discentes, ...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
docente       <- read_csv(here("data", "planilhao", "docente2.csv"))
## Rows: 12522 Columns: 31
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (10): Cod PPG, Nome do docente, Sexo, Faixa Etária, Área de Conhecimento...
## dbl (21): Ano base, ID_Docente, Ano Titulação, Carga horária semanal no prog...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
discente      <- read_csv(here("data", "planilhao", "discente_full.csv"))
## Rows: 37584 Columns: 7
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (5): Cod PPG, Discente, Sexo, Situação Mestrado, Situação Doutorado
## dbl (2): Ano base, Identificador
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
egresso       <- read_csv(here("data", "planilhao", "egresso.csv"))
## Rows: 24003 Columns: 6
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (4): Cod PPG, Egresso, Situação Mestrado, Situação Doutorado
## dbl (2): Ano Titulação Mestrado, Ano Titulação Doutorado
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
destaques <- read_csv(here("data", "destaques", "destaques2.csv"))
## Rows: 11174 Columns: 10
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (10): EVENTO, TIPO EVENTO, IES, Cod PPG, Nome PPG, NIVEL, NOME DO EGRESS...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
malafaia  <- read_csv(here("data", "planilhao", "malafaia.csv")) # retracted articles
## Rows: 47 Columns: 1
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): Titulo da Produção
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
nomes_var  <- read_csv(here("data", "planilhao", "nomes_var.csv"))
## Rows: 95 Columns: 2
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (2): var, nome
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# ===================================================================
# WEIGHTS
# ===================================================================

weights <- tibble::tribble(
  ~Estrato, ~Weight,
  # Artigos
  "A1", 1.00, "A2", 0.85, "A3", 0.70, "A4", 0.60,
  "B1", 0.50, "B2", 0.35, "B3", 0.20, "B4", 0.10,
  # Livros
  "L1", 1.00, "L2", 0.80, "L3", 0.60, "L4", 0.40, "L5", 0.20,
  # Produtos técnicos (PTT)
  "T1", 1.00, "T2", 0.80, "T3", 0.60, "T4", 0.40, "T5", 0.20
)

w <- as.list(setNames(weights$Weight, tolower(weights$Estrato))) 

conceitos <- tibble::tribble(
  ~CONCEITO, ~Weight,
  "Muito bom",     10, 
  "Bom",          7.5, 
  "Regular",        5, 
  "Fraco",        2.5,
  "Insuficiente",   0, 
  "Não aderente",   0)


# ===================================================================
# DATA PREPARATION 
# ===================================================================

programa <- spine |> select(`Ano base`, `Cod PPG`, `Nome PPG`, 
                            `IES Principal Sigla`, `Região`, Modalidade, 
                            Nota, Nível, `Ano de Início`, `Situação`) |> distinct()



ppg_key <- programa |> distinct(`Cod PPG`)


docente_cols_to_transform <- c(
  "Responsável por Projeto com Participação Discente",
  "Responsável com financiamento e participação discente",
  "Turmas ministradas - Responsável",
  "Turmas ministradas - Participante",
  "Atividades na Graduação",
  "Permanente em outros PPGs"
)

cols_to_drop <- c(
  "Orientações em andamento - MP",
  "Orientações em andamento - DP",
  "Orientações concluídas - MP",
  "Orientações concluídas - DP"
)


dp <- docente |>
  filter(Categoria == "PERMANENTE") |>
  mutate(
    # Converte colunas numéricas para flags booleanos (VERDADEIRO/FALSO)
    across(
      any_of(docente_cols_to_transform),
      ~ replace_na(as.numeric(.x), 0) > 0
    ),
    
    # Converte colunas de texto CNPq para flags booleanos
    # Converte NAs e células vazias para FALSO
    across(
      contains("CNPq"),
      ~ !is.na(.x) & .x != ""
    ),
    
    # Processa status de permanência no quadriênio
    `Permanente ao longo do quadriênio` = 
      str_to_upper(trimws(`Permanente ao longo do quadriênio`)) == "SIM",
    
    # Combina orientações em andamento (Mestrado + Mestrado Profissional)
    `Orientações em andamento - ME` = 
      coalesce(`Orientações em andamento - ME`, 0) +
      coalesce(`Orientações em andamento - MP`, 0),
    
    # Combina orientações em andamento (Doutorado + Doutorado Profissional)
    `Orientações em andamento - DO` = 
      coalesce(`Orientações em andamento - DO`, 0) +
      coalesce(`Orientações em andamento - DP`, 0),
    
    # Combina orientações concluídas (Mestrado + Mestrado Profissional)
    `Orientações concluídas - ME` = 
      coalesce(`Orientações concluídas - ME`, 0) +
      coalesce(`Orientações concluídas - MP`, 0),
    
    # Combina orientações concluídas (Doutorado + Doutorado Profissional)
    `Orientações concluídas - DO` = 
      coalesce(`Orientações concluídas - DO`, 0) +
      coalesce(`Orientações concluídas - DP`, 0),
    
    # NOVAS VARIÁVEIS
    
    # Docente não possui orientações
    `Não orientou` = (
      `Orientações em andamento - ME` +
        `Orientações em andamento - DO` +
        `Orientações concluídas - ME` + 
        `Orientações concluídas - DO`
    ) == 0,
    
    # Docente ministrou turmas no PPG
    `Turmas ministradas` = 
      `Turmas ministradas - Responsável` | `Turmas ministradas - Participante`,
    
    # Docente possui bolsa CNPq
    `Bolsista CNPq` = 
      `Bolsa Produtividade - Pesquisa CNPq` | 
      `Bolsa Produtividade - Desen. Tec. e Extensão Inovadora CNPq`,
    
    # Docente é exclusivo (não é permanente em outros PPGs)
    Exclusivo = !`Permanente em outros PPGs`
  ) |>
  
  # Renomeia coluna principal de identificação
  rename(Docente = `Nome do docente`) |>
  
  # Remove colunas desnecessárias
  select(-any_of(cols_to_drop))


egresso <- egresso |>
  mutate(
    # Substitui valores ausentes por "NÃO TITULADO" nas colunas de situação
    across(
      contains("Situação"), 
      ~ replace_na(.x, "NÃO TITULADO")
    ),
    
    # Cria flags booleanos para titulação por nível
    `Titulado Mestrado`  = `Situação Mestrado` == "TITULADO",
    `Titulado Doutorado` = `Situação Doutorado` == "TITULADO",
    
    # Calcula o ano da titulação mais recente entre mestrado e doutorado
    `Ano da Titulação mais Recente` = 
      pmax(`Ano Titulação Mestrado`, `Ano Titulação Doutorado`, na.rm = TRUE)
  ) |>
  
  # Remove colunas de situação originais (já processadas)
  select(-`Situação Mestrado`, -`Situação Doutorado`)


# Processamento dos dados de DISCENTES
discente <- discente |> 
  mutate(
    # Substitui valores ausentes por "NÃO MATRICULADO" nas colunas de situação
    across(
      contains("Situação"), 
      ~ replace_na(.x, "NÃO MATRICULADO")
    ),
    
    # Cria flags booleanos para matrícula por nível
    # Prioriza doutorado sobre mestrado (discente pode estar em ambos)
    `Matriculado Doutorado` = `Situação Doutorado` == "MATRICULADO",
    `Matriculado Mestrado`  = `Situação Mestrado` == "MATRICULADO" & 
      !`Matriculado Doutorado`
  ) |>
  
  # Mantém apenas discentes atualmente matriculados em algum nível
  filter(`Matriculado Doutorado` | `Matriculado Mestrado`)

  
output <- output |>
  filter(str_detect(Estrato, "^(A[1-4]|B[1-4]|L[1-5]|T[1-5])$"),
         Permanente > 0,
         !`Titulo da Produção` %in% malafaia$`Titulo da Produção`) |>
  select(-c(Permanente, Colaborador, Visitante, `Total de Discentes`, Doutorado, `Doutorado Profissional`,   
            Mestrado, `Mestrado Profissional`, `Egresso  Acima de 5 anos`, `Egresso  Até 5 anos`)
  )


# Processamento dos AUTORES das produções científicas
output_autor <- output |>
  
  # Separa múltiplos autores em linhas individuais
  separate_rows(Autores, sep = "\\|") |>
  
  # Remove espaços extras dos nomes dos autores
  mutate(Autores = str_squish(Autores)) |>
  
  # Separa o nome e vínculo do autor
  separate(
    Autores, 
    into = c("Nome", "group"), 
    sep = "\\(", 
    fill = "right"
  ) |>
  
  mutate(
    # Limpa e padroniza o vínculo do autor
    group = str_squish(str_remove(group, "\\)$")),
    Nome = str_squish(Nome),
    
    # Cria chave para o vínculo do autor
    group_key = case_when(
      str_detect(tolower(group), "discente[ _]mestrado")  ~ "discente_mestrado",
      str_detect(tolower(group), "discente[ _]doutorado") ~ "discente_doutorado",
      str_detect(tolower(group), "egresso")               ~ "egresso",
      str_detect(tolower(group), "docente permanente")    ~ "dp"
    ),
    
    # Cria identificador único do autor (nome + vínculo + programa)
    author_key = str_c(Nome, "_", group_key, "_", `Cod PPG`)
  ) |>
  
  # Remove registros onde não foi possível identificar o tipo de vínculo (por exemplo, autores externos)
  filter(!is.na(group_key))


# ===================================================================
# ANÁLISE DOS DADOS
# ===================================================================

# AUTORES POR ESTRATO DE PERIÓDICO =====================================

# Função para filtrar autores por estrato de publicação
filtro_autor_por_estrato <- function(publication_list = output_autor, pattern) {
  publication_list |> 
    filter(str_detect(Estrato, pattern)) |>
    distinct(`Cod PPG`, Nome, group_key, author_key)
}

# Autores com publicações em periódicos A1 e A2 (estratos superiores)
author_A1_A2 <- filtro_autor_por_estrato(pattern = "^(A1|A2)$")

# Autores com publicações em periódicos estrato A (A1, A2, A3, A4)
author_A    <- filtro_autor_por_estrato(pattern = "^A[1-4]$")

# Autores com publicações em periódicos estratos A e B (A1-A4, B1-B4)
author_AB   <- filtro_autor_por_estrato(pattern = "^[AB][1-4]$")


# DISCENTES E EGRESSOS POR NÍVEL ACADÊMICO =============================

# Critérios de inclusão:
# - Discentes: matriculados no último ano do quadriênio (2024)
# - Egressos:  titulados nos últimos cinco anos (2020-2024)

# Discentes de MESTRADO matriculados em 2024
students_master <- discente |>
  filter(`Ano base` == 2024, `Matriculado Mestrado`) |>
  mutate(group = "discente_mestrado") |> 
  select(`Cod PPG`, Nome = Discente, group) |>
  distinct()

# Discentes de DOUTORADO matriculados em 2024
students_phd <- discente |>
  filter(`Ano base` == 2024, `Matriculado Doutorado`) |>
  mutate(group = "discente_doutorado") |>
  select(`Cod PPG`, Nome = Discente, group) |>
  distinct()

# Egressos de MESTRADO titulados entre 2020-2024
graduates_master <- egresso |>
  filter(`Ano da Titulação mais Recente` >= 2020, `Titulado Mestrado`) |>
  mutate(group = "egresso_mestrado") |>
  select(`Cod PPG`, Nome = Egresso, group) |>
  distinct()

# Egressos de DOUTORADO titulados entre 2020-2024
graduates_phd <- egresso |>
  filter(`Ano da Titulação mais Recente` >= 2020, `Titulado Doutorado`) |>
  mutate(group = "egresso_doutorado") |>
  select(`Cod PPG`, Nome = Egresso, group) |>
  distinct()


# ANÁLISE DE DISCENTES E EGRESSOS POR ESTRATO DE PERIÓDICO ===============

# Consolida todos os discentes e egressos elegíveis para análise
# Critérios: Discentes matriculados em 2024 OU Egressos titulados 2020-2024
students_graduates <- bind_rows(
  students_master,
  students_phd,
  graduates_master,
  graduates_phd
) |>
  # Padroniza as chaves de grupo 
  mutate(group_key = case_when(
      str_detect(tolower(group), "discente[ _]mestrado")  ~ "discente_mestrado",
      str_detect(tolower(group), "discente[ _]doutorado") ~ "discente_doutorado",
      str_detect(tolower(group), "egresso")               ~ "egresso"
    ),
    author_key = str_c(Nome, "_", group_key, "_", `Cod PPG`)
  ) |>
  
  # Verifica se cada discente/egresso possui publicações nos diferentes estratos
  mutate(
    author_A1_A2 = author_key %in% author_A1_A2$author_key, 
    author_A     = author_key %in% author_A$author_key, 
    author_AB    = author_key %in% author_AB$author_key
  ) |>
  
  # Calcula estatísticas por PPG e grupo (discente mestrado, discente doutorado e egresso)
  group_by(`Cod PPG`, group) |>
  summarize(
    total         = n(),                    # Total de indivíduos no grupo
    estrato_A1_A2 = sum(author_A1_A2),      # Quantos publicaram em A1/A2
    estrato_A     = sum(author_A),          # Quantos publicaram em A
    estrato_AB    = sum(author_AB),         # Quantos publicaram em A ou B
    .groups = 'drop' 
  ) |>
  
  # Transforma dados de formato longo para formato amplo (Excel)
  # Cada métrica (total, A1_A2, A, AB) vira uma coluna separada por grupo
  pivot_longer(
    cols = c("total", "estrato_A1_A2", "estrato_A", "estrato_AB"), 
    names_to  = "metrica",
    values_to = "count"
  ) |>
  
  # Cria nomes de colunas combinando grupo e métrica
  mutate(group_metrica = paste0(group, "_", metrica)) |>
  select(-group, -metrica) |>
  
  # Converte para formato final: uma linha por PPG, colunas para cada combinação
  pivot_wider(
    names_from = group_metrica, 
    values_from = count,
    values_fill = 0
  ) |>
  # Adiciona informações dos PPGs e preenche valores ausentes
  right_join(ppg_key, by = "Cod PPG") |>
  mutate(across(everything(), ~ replace_na(.x, 0)))

    
# PRODUÇÃO QUALIFICADA DE DISCENTES E EGRESSOS ============================

# Critérios de qualificação da produção:
# - Artigos: estratos A (A1-A4) ou B (B1-B4)
# - Livros : estratos L (L1-L5) 
# - Produtos Técnicos e Tecnológicos (PTT): estratos T (T1-T5)

# Consolida produção de discentes e egressos durante o quadriênio
students_graduates_output <- bind_rows(
  # Todos os discentes do período
  discente |> select(`Cod PPG`, Nome = Discente),
  # Todos os egressos do período  
  egresso |> select(`Cod PPG`, Nome = Egresso)
) |>
  # Remove duplicatas (mesmo indivíduo pode ser discente e egresso)
  distinct() |>
  
  # Conecta com as produções dos discentes/egressos 
  inner_join(
    output_autor |>
      filter(str_detect(group_key, "discente|egresso")),
    by = c("Cod PPG", "Nome")
  ) |>
  
  # Uma produção conta apenas uma vez por programa
  distinct(`Cod PPG`, `Titulo da Produção`, Estrato) |>
  
  # Conta produções por PPG e estrato
  count(`Cod PPG`, Estrato) |>
  
  # Completa combinações ausentes (PPG sem produção em determinado estrato) com 0
  complete(`Cod PPG`, Estrato, fill = list(n = 0))


# INDICADOR DE PRODUÇÃO DISCENTE/EGRESSO (INDProd) ========================

# Fórmula: Produção qualificada ponderada / Total ponderado de discentes (2024) e egressos (2020-2024)
# 
# Ponderação do denominador:
# - 1 discente/egresso de mestrado = peso 1
# - 1 discente/egresso de doutorado = peso 2

indprod_disc <- students_graduates_output |> 
  
  # Adiciona pesos por estrato de produção
  left_join(weights, by = "Estrato") |>
  
  # Calcula produção ponderada (quantidade × peso do estrato)
  mutate(weighted_output = n * Weight) |>
  
  # Soma produção ponderada total por PPG (numerador do INDProd discente/egresso)
  count(
    `Cod PPG`, 
    wt = weighted_output, 
    name = "INDProd_disc_numerador"
  ) |>
  
  # Garante que PPGs sem produção tenham numerador = 0 (boa prática como salvaguarda)
  mutate(INDProd_disc_numerador = replace_na(INDProd_disc_numerador, 0)) |>
  
  # Adiciona o total de discentes/egressos para calcular denominador
  left_join(students_graduates, by = "Cod PPG") |>
  
  # Calcula denominador ponderado e INDProd final
  mutate(
    # Denominador: mestres (peso 1) + doutores (peso 2)
    INDProd_disc_denominador = 
      1 * (discente_mestrado_total  + egresso_mestrado_total) +
      2 * (discente_doutorado_total + egresso_doutorado_total),
    
    A1_A2_count = 
      1 * (discente_mestrado_estrato_A1_A2  + egresso_mestrado_estrato_A1_A2) +
      2 * (discente_doutorado_estrato_A1_A2 + egresso_doutorado_estrato_A1_A2),
    
    A_count = 
      1 * (discente_mestrado_estrato_A  + egresso_mestrado_estrato_A) +
      2 * (discente_doutorado_estrato_A + egresso_doutorado_estrato_A),
    
    AB_count = 
      1 * (discente_mestrado_estrato_AB  + egresso_mestrado_estrato_AB) +
      2 * (discente_doutorado_estrato_AB + egresso_doutorado_estrato_AB),
    
    A1_A2_prop = if_else(INDProd_disc_denominador == 0, 0,
                         A1_A2_count * 100 / INDProd_disc_denominador),
    
    A_prop = if_else(INDProd_disc_denominador == 0, 0,
                     A_count * 100 / INDProd_disc_denominador),
    
    AB_prop = if_else(INDProd_disc_denominador == 0, 0,
                      AB_count * 100 / INDProd_disc_denominador),
    
    `INDProd disc` = if_else(INDProd_disc_denominador == 0, 0,
                             INDProd_disc_numerador / INDProd_disc_denominador)
  ) |>
  
  relocate(INDProd_disc_numerador, .before = INDProd_disc_denominador) |>
  select(-matches("count|discente|egresso"))


# For excel users
# Possibilita que o Consultor valide o cálculo na planilha

indprod_disc_check <- students_graduates_output |> 
  pivot_wider(names_from = Estrato, values_from = n, values_fill = 0, names_sort = T) |>
  left_join(students_graduates, by = "Cod PPG") |>
  mutate(INDProd_disc_numerador =
           (w$a1 * A1) + (w$a2 * A2) + (w$a3 * A3) + (w$a4 * A4) +
           (w$b1 * B1) + (w$b2 * B2) + (w$b3 * B3) + (w$b4 * B4) +
           (w$l1 * L1) + (w$l2 * L2) + (w$l3 * L3) + (w$l4 * L4) + (w$l5 * L5) +
           (w$t1 * T1) + (w$t2 * T2) + (w$t3 * T3) + (w$t4 * T4) + (w$t5 * T5),
         INDProd_disc_numerador = replace_na(INDProd_disc_numerador, 0),
         INDProd_disc_denominador = 
                    1 * (discente_mestrado_total  + egresso_mestrado_total) +
                    2 * (discente_doutorado_total + egresso_doutorado_total),
                  `INDProd disc` = INDProd_disc_numerador / INDProd_disc_denominador) |>
           arrange(desc(`INDProd disc`))


# CONTAGEM DE DOCENTES PERMANENTES ==========================================

# Número total de Docentes Permanentes por PPG e Ano
dp_count <- dp |> 
  distinct(`Ano base`, `Cod PPG`, Docente) |>
  count(
    `Ano base`, 
    `Cod PPG`, 
    name = "dp_count"
  )

# Número de Docentes Permanentes sêniores por PPG e Ano
# (exclui JPD - Jovens Doutores Permanentes com titulação há 5 anos ou menos)
dp_senior_count <- dp |> 
  filter(`Ano base` - `Ano Titulação` > 5) |>
  distinct(`Ano base`, `Cod PPG`, Docente) |>
  count(
    `Ano base`, 
    `Cod PPG`, 
    name = "dp_senior_count"
  )

# Número médio de Docentes Permanentes por PPG no Quadriênio
dp_count_quadri <- dp |> 
  distinct(`Cod PPG`, `Ano base`, Docente) |>
  count(`Cod PPG`, `Ano base`) |>
  summarize(
    dp_count_quadri = mean(n), 
    .by = `Cod PPG`
  )

contagem <- dp_count |>
  left_join(dp_senior_count, by = c("Ano base", "Cod PPG")) |>
  left_join(dp_count_quadri, by = c("Cod PPG")) |> 
  left_join(indprod_disc |> 
              select(`Cod PPG`, disc_count = INDProd_disc_denominador),
            by = "Cod PPG")


# PRODUTIVIDADE DOCENTE ====================================================

# Função para calcular indicadores de produtividade
# Calcula INDProd para docentes permanentes totais e sêniores
calculate_productivity <- function(data, numerator_col, indicator_name) {
  data |>
    # Adiciona contagem de docentes permanentes por ano e PPG
    left_join(dp_count, by = c("Ano base", "Cod PPG")) |> 
    left_join(dp_senior_count, by = c("Ano base", "Cod PPG")) |>
    
    # Trata valores ausentes e calcula indicadores
    mutate(
      dp_count = replace_na(dp_count, 0),
      dp_senior_count = replace_na(dp_senior_count, 0),
      
      # INDProd = Produção ponderada / Total de docentes permanentes
      !!paste0("INDProd ", indicator_name) := 
        ifelse(dp_count == 0, 0, !!sym(numerator_col) / dp_count),
      
      # INDProd sênior = Produção ponderada / Docentes sêniores (>5 anos pós-doutorado)
      !!paste0("INDProd ", indicator_name, " DP senior") := 
        ifelse(dp_senior_count == 0, 0, !!sym(numerator_col) / dp_senior_count)
    )
}

# PREPARAÇÃO DOS DADOS DE PRODUÇÃO DOCENTE =================================

# Consolida os DPs por PPG e Ano
producao_docente <- dp |>
  select(`Ano base`, `Cod PPG`, Nome = Docente) |>
  distinct() |>
  
  # Conecta com produções dos DPs
  inner_join(output_autor, by = c("Cod PPG", "Ano base", "Nome")) |>
  
  # Uma produção conta apenas uma vez por PPG e Ano
  distinct(`Cod PPG`, `Titulo da Produção`, `Ano base`, Estrato) |>
  
  # Conta produções por PPG, ANO e Estrato
  count(`Cod PPG`, `Ano base`, Estrato) |> 
  
  # Completa combinações ausentes com zero 
  complete(`Cod PPG`, `Ano base`, Estrato, fill = list(n = 0)) |>
  
  # Adiciona pesos por estrato e calcula produção ponderada
  left_join(weights, by = "Estrato") |>
  mutate(weighted_output = n * Weight) |>
  
  # Mantém apenas PPGs e anos presentes nos dados de docentes
  semi_join(docente, by = c("Cod PPG", "Ano base"))

# CÁLCULO DOS INDICADORES POR TIPO DE PRODUÇÃO ============================

# INDProd ARTIGOS estratos A (A1-A4)
indprod_article_a_num <- producao_docente |>
  filter(str_detect(Estrato, "^[A][1-4]")) |> 
  count(`Cod PPG`, `Ano base`,
        wt = weighted_output, name = "indprod_article_a_num")

# INDProd ARTIGOS estratos B (B1-B4)  
indprod_article_b_num <- producao_docente |>
  filter(str_detect(Estrato, "^[B][1-4]")) |> 
  count(`Cod PPG`, `Ano base`,
        wt = weighted_output, name = "indprod_article_b_num")

# INDProd ARTIGOS combinado (A + B limitado)
# Regra CAPES: produção B pode contribuir no máximo 25% do indicador final
indprod_artigo <- indprod_article_a_num |> 
  left_join(indprod_article_b_num, by = c("Cod PPG", "Ano base")) |>
  mutate(
    indprod_article_a_num = replace_na(indprod_article_a_num, 0),
    indprod_article_b_num = replace_na(indprod_article_b_num, 0),
    
    # Limite B: máximo 25% do total => B ≤ A/3 (pois A + B/3 = A × 1.33, B = 25%)
    limit_b_25pct_of_final = indprod_article_a_num / 3,
    indprod_article_b_num_adj = pmin(indprod_article_b_num, limit_b_25pct_of_final),
    
    # Numerador final: A + B ajustado
    indprod_artigo_numerador = indprod_article_a_num + indprod_article_b_num_adj
  ) |>
  
  # Remove colunas intermediárias
  select(-indprod_article_a_num, -indprod_article_b_num, 
         -indprod_article_b_num_adj, -limit_b_25pct_of_final) |>
  
  # Calcula o indicador final
  calculate_productivity("indprod_artigo_numerador", "Artigo")

# INDProd LIVROS (estratos L1-L5)
indprod_livro <- producao_docente |>
  filter(str_detect(Estrato, "^[L][1-5]")) |> 
  count(`Cod PPG`, `Ano base`,
        wt = weighted_output, name = "indprod_livro_numerador") |>
  calculate_productivity("indprod_livro_numerador", "Livro")

# INDProd PRODUTOS TÉCNICOS E TECNOLÓGICOS - PTT (estratos T1-T5)
indprod_tec <- producao_docente |>
  filter(str_detect(Estrato, "^[T][1-5]")) |> 
  count(`Cod PPG`, `Ano base`,
        wt = weighted_output, name = "indprod_tec_numerador") |>
  calculate_productivity("indprod_tec_numerador", "PTT")

# INDProd GERAL (todos os estratos qualificados)
indprod_geral <- producao_docente |>
  count(`Cod PPG`, `Ano base`,
        wt = weighted_output, name = "indprod_geral_numerador") |>
  calculate_productivity("indprod_geral_numerador", "Geral")


# TABELA FINAL DE INDICADORES DE PRODUÇÃO ======================================

# Lista com todos os indicadores calculados
indprod_list <- list(
  indprod_artigo = indprod_artigo,
  indprod_livro  = indprod_livro,
  indprod_tec    = indprod_tec,
  indprod_geral  = indprod_geral
)

# Combina todos os indicadores em uma única tabela
indprod <- reduce(
  indprod_list,
  left_join, 
  by = c("Ano base", "Cod PPG", "dp_count", "dp_senior_count")
) |>
  # Remove colunas de numeradores (mantém apenas indicadores finais)
  select(-contains("numerador"), -contains("count"))

# Média dos indicadores para o quadriênio
indprod_quadri <- indprod |>
  dplyr::group_by(`Cod PPG`) |>
  dplyr::summarise(
    dplyr::across(dplyr::starts_with("INDProd"),
                  ~ sum(.x, na.rm = TRUE),
                  .names = "{.col}_sum"),
    .groups = "drop"
  ) |> left_join(dp |> 
                   distinct(`Ano base`, `Cod PPG`) |>
                   count(`Cod PPG`),
                 by = "Cod PPG") |>
  dplyr::mutate(
    dplyr::across(
      dplyr::matches("^INDProd.*_sum$"),
      ~ .x / n,
      .names = "{.col}_per_year"
    )
  ) |> select(-ends_with("sum"))



indprod_check <- dp |>
  select(`Ano base`, `Cod PPG`, Nome = Docente) |>
  distinct() |>
  inner_join(output_autor, by = c("Cod PPG", "Ano base", "Nome")) |>
  distinct(`Cod PPG`, `Titulo da Produção`, `Ano base`, Estrato) |>
  count(`Cod PPG`, `Ano base`, Estrato) |>
  pivot_wider(names_from = Estrato, values_from = n, 
              values_fill = 0, names_sort = T) |>
  mutate(INDProd_artigo_numerador_a = 
           (w$a1 * A1) + (w$a2 * A2) + (w$a3 * A3) + (w$a4 * A4),
         INDProd_artigo_numerador_b = 
           (w$b1 * B1) + (w$b2 * B2) + (w$b3 * B3) + (w$b4 * B4),
         limit_b_25pct_of_final =  INDProd_artigo_numerador_a / 3,
         indprod_article_b_num_adj = pmin(INDProd_artigo_numerador_b, limit_b_25pct_of_final),
         INDProd_artigo_numerador =  INDProd_artigo_numerador_a + indprod_article_b_num_adj,
         INDProd_livro_numerador =
           (w$l1 * L1) + (w$l2 * L2) + (w$l3 * L3) + (w$l4 * L4) + (w$l5 * L5),
         INDProd_tec_numerador =
           (w$t1 * T1) + (w$t2 * T2) + (w$t3 * T3) + (w$t4 * T4) + (w$t5 * T5)
  ) |>
  left_join(dp_count, by = c("Ano base", "Cod PPG")) |> 
  mutate(
    dp_count = replace_na(dp_count, 0),
    # Safe division to prevent Inf values
    `INDProd Artigo` = ifelse(dp_count > 0, INDProd_artigo_numerador / dp_count, 0),
    `INDProd Livro`  = ifelse(dp_count > 0, INDProd_livro_numerador / dp_count, 0),
    `INDProd PTT`    = ifelse(dp_count > 0, INDProd_tec_numerador / dp_count, 0)
  ) |> right_join(dp |> distinct(`Ano base`, `Cod PPG`),
                  by = c("Ano base", "Cod PPG")) |>
  mutate(across(everything(),
                ~ replace_na(.x, 0)))


# Resultados convergem?

indprod_disc |>
  select(`Cod PPG`, `INDProd disc`) |>
  full_join(indprod_disc_check |> 
              select(`Cod PPG`, `INDProd disc`), 
            by = "Cod PPG", suffix = c("", "_check")) |>
  mutate(check = dplyr::near(`INDProd disc`, `INDProd disc_check`)) |>
  summarise(all_methods_converge = all(check, na.rm = TRUE))
## # A tibble: 1 × 1
##   all_methods_converge
##   <lgl>               
## 1 FALSE
indprod |>
  select(`Ano base`, `Cod PPG`, `INDProd Artigo`, `INDProd Livro`, `INDProd PTT`) |>
  full_join(indprod_check |>
              select(`Ano base`, `Cod PPG`, `INDProd Artigo`, `INDProd Livro`, `INDProd PTT`), 
            by = c("Cod PPG", "Ano base"), suffix = c("", "_check")) |>
  mutate(check_artigo = dplyr::near(`INDProd Artigo`, `INDProd Artigo_check`),
         check_livro = dplyr::near(`INDProd Livro`, `INDProd Livro_check`),     
         check_tec = dplyr::near(`INDProd PTT`, `INDProd PTT_check`)) |>
  summarise(
    all_methods_converge = all(check_artigo, check_livro, check_tec, na.rm = TRUE)
  )
## # A tibble: 1 × 1
##   all_methods_converge
##   <lgl>               
## 1 TRUE
# ANÁLISE DOS DESTAQUES =====================================================

# Níveis ordenados de conceitos 
conceito_levels <- c("Muito bom", "Bom", "Regular", "Fraco", "Insuficiente", "Não aderente")


# CONTAGEM ABSOLUTA DE DESTAQUES POR CONCEITO =============================
destaques_n <- destaques |>
  filter(!is.na(CONCEITO), !is.na(EVENTO), !is.na(`Cod PPG`)) |>
  mutate(CONCEITO = factor(CONCEITO, levels = conceito_levels)) |>
  count(`Cod PPG`, EVENTO, CONCEITO) |>
  complete(`Cod PPG`, EVENTO, CONCEITO, fill = list(n = 0)) |>
  arrange(EVENTO, CONCEITO) |>
  pivot_wider(
    names_from  = c(EVENTO, CONCEITO),
    names_glue  = "{EVENTO}_{CONCEITO}",
    values_from = n,
    values_fill = 0,
    names_sort  = FALSE
  )

# PROPORÇÃO DE DESTAQUES POR CONCEITO ======================================
destaques_p <- destaques |>
  filter(!is.na(CONCEITO), !is.na(EVENTO), !is.na(`Cod PPG`)) |>
  mutate(
    CONCEITO = factor(CONCEITO, levels = conceito_levels)
  ) |>
  count(`Cod PPG`, EVENTO, CONCEITO) |> 
  complete(`Cod PPG`, EVENTO, CONCEITO, fill = list(n = 0)) |>
  group_by(`Cod PPG`, EVENTO) |>
  mutate(
    total_n = sum(n),
    p = if_else(total_n == 0, 0, n / total_n)
  ) |>
  ungroup() |>
  arrange(EVENTO, CONCEITO) |>
  select(-n, -total_n) |>  # Remove both n and total_n after using them
  pivot_wider(
    names_from  = c(EVENTO, CONCEITO),
    names_glue  = "{EVENTO}_{CONCEITO}",
    values_from = p,
    values_fill = 0,
    names_sort  = FALSE        
  )

#  CONCEITO PREDOMINANTE =====================================
destaques_mark <- destaques |>
  filter(!is.na(CONCEITO), !is.na(EVENTO), !is.na(`Cod PPG`)) |>
  mutate(
    CONCEITO = factor(CONCEITO, levels = conceito_levels)
  ) |>
  count(`Cod PPG`, EVENTO, CONCEITO) |> 
  complete(`Cod PPG`, EVENTO, CONCEITO, fill = list(n = 0)) |>
  group_by(`Cod PPG`, EVENTO) |>
  left_join(conceitos, by = "CONCEITO") |>
  mutate(Weight = coalesce(Weight, 0)) |>
  mutate(
    total_n = sum(n),
    p = if_else(total_n == 0, 0, n / total_n),
    mark = p * Weight         
  ) |>
  summarise(nota = sum(mark), .groups = "drop") |>
  mutate(conceito = case_when(
    nota == 0                ~ "Insuficiente ou não aderente",
    nota > 0    & nota < 2.5 ~ "Fraco",
    nota >= 2.5 & nota < 5   ~ "Regular",
    nota >= 5   & nota < 7.5 ~ "Bom",
    nota >= 7.5              ~ "Muito bom"
  )) |>
  select(-nota) |>
  pivot_wider(
    names_from  = EVENTO,
    values_from = conceito,
    values_fill = "Insuficiente ou não aderente",
    names_sort  = FALSE        
  )


#  IMPACTO NA CIÊNCIA =====================================

# Contagem fracionada de publicações -------------------------------------------
# Alternativa* para calcular o indicador de impacto na sociedade (3.1)
  # "Cada produto técnico/tecnológico e bibliográfico 
  #  será contabilizado apenas uma vez por PPG."

calculate_fractional_authorship <- function(faculty_data, publication_data, 
                                            estrato_filter,
                                            min_publications = 2) { 
  
  faculty_list <- faculty_data |>
    distinct(`Cod PPG`, Nome = Docente)
  
  authorship_data <- publication_data |>
    filter(Estrato == estrato_filter) |>
    inner_join(faculty_list, by = c("Cod PPG", "Nome")) |>
    select(`Cod PPG`, `Titulo da Produção`, Nome)
  
  fr_counts_publication <- authorship_data |>
    count(`Cod PPG`, `Titulo da Produção`) |>
    mutate(fr_count = 1 / n)
  
  fr_counts_author <- authorship_data |>
    left_join(fr_counts_publication, by = c("Cod PPG", "Titulo da Produção")) |>
    count(`Cod PPG`, Nome, wt = fr_count, sort = TRUE, name = "author_output_fr") |>
    filter(author_output_fr >= min_publications)
}

docente_output_A1_cont_fr <- calculate_fractional_authorship(
  faculty_data = dp,         
  publication_data = output_autor, 
  estrato_filter = "A1",
  min_publications = 2) 
  
docente_output_A2_cont_fr <- calculate_fractional_authorship(
  faculty_data = dp,          
  publication_data = output_autor, 
  estrato_filter = "A2",
  min_publications = 2)

docente_output_T1_cont_fr <- calculate_fractional_authorship(
  faculty_data = dp,         
  publication_data = output_autor, 
  estrato_filter = "T1",
  min_publications = 2)

docente_output_T2_cont_fr <- calculate_fractional_authorship(
  faculty_data = dp,          
  publication_data = output_autor, 
  estrato_filter = "T2",
  min_publications = 2)


list_of_counts <- list(
  A1 = docente_output_A1_cont_fr,
  A2 = docente_output_A2_cont_fr,
  T1 = docente_output_T1_cont_fr,
  T2 = docente_output_T2_cont_fr
)

  summaries <- purrr::map(list_of_counts, ~ dplyr::count(.x, `Cod PPG`)) |>
  purrr::map2(
    names(list_of_counts),
    ~ dplyr::rename(.x, !!paste0("autores_", .y, "_fr_gte_2") := n)
  )

  
  docente_fractional_summary <- purrr::reduce(
    .x    = summaries,
    .f    = dplyr::left_join,
    by    = "Cod PPG",
    .init = ppg_key
  ) |>
    right_join(dp_count_quadri, by = "Cod PPG") |>
    mutate(
      across(
        .cols = where(is.numeric) & !any_of("dp_count_quadri"),
        .fns  = ~ replace_na(.x, 0)
      )
    ) |> mutate(
      denom = coalesce(dp_count_quadri, 0),
      across(
        ends_with("_fr_gte_2"),
        ~ if_else(denom > 0, .x * 100 / denom, 0),
        .names = "{.col}_prop"
      )
    ) |>
    select(-denom, -contains("count"))
  
  
# --- CONCENTRAÇÃO EDITORIAL E AUTORAL --------------------------------------------

# Índice de Concentração Editorial 
# (Número de publicações no periódico mais frequente * 100) / (Total de publicações)

ICE <- output |>
    filter(Estrato %in% c("A1", "A2", "A3", "A4", "B1", "B2", "B3", "B4")) |>
    distinct(`Cod PPG`, Source, `Titulo da Produção`) |>
    count(`Cod PPG`, Source, name = "pub_count") |>
    group_by(`Cod PPG`) |>
    mutate(
      total_pub = sum(pub_count),
      ICE = pub_count * 100 / total_pub) |>
    slice_max(order_by = pub_count, n = 1, with_ties = TRUE) |>
    summarize(
      `Periódico mais frequente` = str_c(Source, collapse = " | "),
      ICE = first(ICE),  # All tied sources have the same ICE value
      n_publicacoes_periodico = first(pub_count),
      total_publicacoes = first(total_pub)
    ) |>
    select(`Cod PPG`, ICE, `Periódico mais frequente`)
  

# --- Índice de Concentração Autoral (Alternative Calculation) ---
# Formula: (Número de publicações do autor mais frequente * 100) / (Total de publicações *únicas*)

author_pub_counts <- output_autor |>
  filter(Estrato %in% c("A1", "A2", "A3", "A4", "B1", "B2", "B3", "B4")) |>
  distinct(`Cod PPG`, Nome, `Titulo da Produção`) |>
  count(`Cod PPG`, Nome, name = "pub_count")

total_pub_counts <- output_autor |>
  filter(Estrato %in% c("A1", "A2", "A3", "A4", "B1", "B2", "B3", "B4")) |>
  distinct(`Cod PPG`, `Titulo da Produção`) |>
  count(`Cod PPG`, name = "total_pub_unique")

ICA  <- author_pub_counts |>
  left_join(total_pub_counts, by = "Cod PPG") |>
  group_by(`Cod PPG`) |>
  mutate(
    ICA = pub_count * 100 / total_pub_unique
  ) |>
  slice_max(order_by = pub_count, n = 1, with_ties = TRUE) |>
  summarize(
    `Autor mais frequente` = str_c(Nome, collapse = " | "),
    ICA = first(ICA),  # All tied authors have the same ICA value
    n_publicacoes_autor = first(pub_count),
    total_publicacoes = first(total_pub_unique) # Using the new total
  ) |>
  select(`Cod PPG`, ICA, `Autor mais frequente`)


# --- ORIENTAÇÕES --------------------------------------------

# Lista de funções para sumarização
summary_funs <- list(
  total   = ~ sum(.x, na.rm = TRUE),
  desvpad = ~ sd(.x, na.rm = TRUE)
)

# Pipeline de transformação de dados
dp_orientacao <- dp |>
  # Cria variáveis compostas (ME = peso 1, DO = peso 2)
  mutate(
    orientacao_andamento = `Orientações em andamento - ME` +
      `Orientações em andamento - DO`,
    orientacao_concluida = 
      1 * `Orientações concluídas - ME` +
      2 * `Orientações concluídas - DO`
  ) |>
  select(`Ano base`, `Cod PPG`, orientacao_andamento, orientacao_concluida) |>
  group_by(`Ano base`, `Cod PPG`) |>
  summarise(
    across(
      .cols = starts_with("orientacao"),
      .fns = summary_funs,
      .names = "{.fn}_{.col}"
    ),
    .groups = "drop"
  ) |>
  left_join(contagem, by = c("Ano base", "Cod PPG")) |>
  mutate(
    # Garante que contagens nulas (NA) sejam tratadas como 0
    dp_count = replace_na(dp_count, 0),
    dp_senior_count = replace_na(dp_senior_count, 0),
    
    # Calcula as médias por tipo de docente
    media_orientacao_andamento_dp =
      if_else(dp_count == 0, 0, total_orientacao_andamento / dp_count),
    media_orientacao_andamento_dp_senior =
      if_else(dp_senior_count == 0, 0, total_orientacao_andamento / dp_senior_count),
    media_orientacao_concluida_dp =
      if_else(dp_count == 0, 0, total_orientacao_concluida / dp_count),
    media_orientacao_concluida_dp_senior =
      if_else(dp_senior_count == 0, 0, total_orientacao_concluida / dp_senior_count),
    
    # Calcula os Coeficientes de Variação (CV%)
    CV_orientacao_andamento =
      if_else(media_orientacao_andamento_dp == 0, 0,
              desvpad_orientacao_andamento * 100 / media_orientacao_andamento_dp),
    CV_orientacao_concluida =
      if_else(media_orientacao_concluida_dp == 0, 0,
              desvpad_orientacao_concluida * 100 / media_orientacao_concluida_dp)
  ) |>
  select(-starts_with("total"), 
         -contains("count"))



# --- PUBLICAÇÕES POR ESTRATO -------------------------------



get_estrato_wide <- function(publication_list = output_autor, 
                             affiliation_group = "dp",
                             count_var = "dp_count") {
  
  publication_list |> 
    filter(group_key %in% affiliation_group) |> 
    distinct(`Cod PPG`, `Ano base`, `Titulo da Produção`, Estrato) |>
    count(`Ano base`, `Cod PPG`, Estrato) |>
    complete(`Cod PPG`, `Ano base`, Estrato, fill = list(n = 0)) |>
    right_join(contagem, by = c("Cod PPG", "Ano base")) |>
    mutate(norm_value = n / .data[[count_var]]) |> 
    select(-n, -contains("count")) |>
    pivot_wider(names_from = Estrato, 
                values_from = norm_value,  # Or use count_norm if normalized values are desired
                values_fill = 0, 
                names_sort = TRUE)
}


get_estrato_sum <- function(publication_list, 
                            affiliation_group = "dp",
                            estrato_pattern = "^[AB][1-4]$", 
                            estrato_nome = "AB") {
  
  publication_list|> 
  filter(group_key %in% affiliation_group) |> 
  distinct(`Cod PPG`, `Ano base`, `Titulo da Produção`, Estrato) |>
  filter(str_detect(Estrato, estrato_pattern)) |>
  count(`Ano base`, `Cod PPG`, Estrato) |>
  complete(`Cod PPG`, `Ano base`, Estrato, fill = list(n = 0)) |>
  right_join(contagem, by = c("Cod PPG", "Ano base")) |>
  select(-contains("count")) |>
  count(`Cod PPG`, `Ano base`, wt = n, name = estrato_nome) |>
  right_join(contagem, by = c("Cod PPG", "Ano base")) |>
    mutate(!!sym(estrato_nome) := replace_na(.data[[estrato_nome]], 0)) |>
    select(-contains("count"))
  }

dp_AB <- get_estrato_sum(publication_list = output_autor, 
                         affiliation_group = "dp",
                         estrato_pattern = "^[AB][1-4]$", 
                         estrato_nome = "dp_AB")

dp_A <- get_estrato_sum(publication_list = output_autor, 
                         affiliation_group = "dp",
                         estrato_pattern = "^[A][1-4]$", 
                         estrato_nome = "dp_A")

dp_estrato_sup_prop <- left_join(dp_AB , dp_A, by = c("Ano base", "Cod PPG")) |>
  mutate(dp_estrato_sup_prop = ifelse(dp_AB == 0, 0, 
                                      dp_A * 100 / dp_AB)) |>
           select(-ends_with("_A"), -ends_with("_AB"))
  
  

estrato_wide_do <- get_estrato_wide(
  publication_list = output_autor,
  affiliation_group = "dp",
  count_var = "dp_count"  # Specify the correct variable
)

estrato_wide_di <- get_estrato_wide(
  publication_list = output_autor,
  affiliation_group = c("discente_mestrado", "discente_doutorado", "egresso"),
  count_var = "disc_count"  # Specify the correct variable
)


estrato_wide <- left_join(estrato_wide_do, estrato_wide_di,
                          by = c("Ano base", "Cod PPG"), 
                          suffix = c("_do", "_di")
) 


# --- PROPORÇÕES --------------------------------------------

dp_colab <- docente |>
  count(`Ano base`, `Cod PPG`, Categoria) |>
  pivot_wider(names_from = Categoria, values_from = n, values_fill = 0) |>
  rename(dp_count = PERMANENTE, 
         colab_count = COLABORADOR) |>
  mutate(colab_prop = colab_count * 100 / (dp_count + colab_count),
         colab_max_30 = colab_prop >= 30,
         colaborador = colab_count
  ) |>
  select(-contains("count"), -contains("VISITANTE"))


dp_estavel_prop <- dp |> 
              distinct(`Cod PPG`, `Ano base`, Docente) |>
              count(`Cod PPG`, Docente) |>
              filter(n == 4) |> 
  count(`Cod PPG`, name = "p_count_quadrienio_estavel") |> 
  left_join(dp_count_quadri, by = "Cod PPG") |>
  mutate(dp_estavel_prop = if_else(coalesce(dp_count_quadri, 0) > 0,
                                   p_count_quadrienio_estavel * 100 / dp_count_quadri, 0)) |>
  select(-contains("count"))


dp_carga_horaria_semanal_min_10h <- dp |>
  group_by(`Ano base`, `Cod PPG`) |>
  summarize(dp_carga_horaria_semanal_min_10h =
                        any(!is.na(`Carga horária semanal no programa`)) &&
                        all(`Carga horária semanal no programa` >= 10, na.rm = TRUE))
## `summarise()` has grouped output by 'Ano base'. You can override using the
## `.groups` argument.
dp_min <- contagem |>
  mutate(dp_min_12 = dp_count >= 12) |>
  select(-contains("count"))
    
  
df_prop_data <- tibble::tribble(
  ~name, ~column,
  "dp_exclusivo",         "Exclusivo",
  "dp_bolsista",          "Bolsista CNPq",
  "dp_proj_responsavel_discente",        "Responsável por Projeto com Participação Discente",
  "dp_proj_responsavel_discente_financ", "Responsável com financiamento e participação discente",
  "dp_nao_orientou",      "Não orientou",
  "dp_turma_ministrada",  "Turmas ministradas",
  "dp_graduacao",         "Atividades na Graduação"
)


list_prop_indicators <- pmap(
  df_prop_data,
  function(name, column, df = dp, df_count = dp_count) {
    
    name_count <- glue("{name}_count")
    name_prop  <- glue("{name}_prop")
    
    df_count |> 
      left_join(
        df |> 
          filter(.data[[column]]) |>
          count(`Ano base`, `Cod PPG`, name = "x_count"), 
        by = c("Ano base", "Cod PPG")
      ) |>
      mutate(
        x_prop = x_count * 100 / dp_count,
        !!name_count := replace_na(x_count, 0),
        !!name_prop  := replace_na(x_prop, 0)
      ) |>
      select(-x_count, -x_prop)
  }
)

prop_indicators <- reduce(list_prop_indicators, left_join, 
                             by = c("Ano base", "Cod PPG")) |>
  select(-contains("count"))


prop_summary <- contagem |>
  left_join(dp_estavel_prop, by = "Cod PPG") |>
  left_join(dp_colab, by = c("Ano base", "Cod PPG")) |>
  left_join(dp_carga_horaria_semanal_min_10h, by = c("Ano base", "Cod PPG")) |>
  left_join(dp_min, by = c("Ano base", "Cod PPG")) |>
  left_join(prop_indicators, by = c("Ano base", "Cod PPG")) 


list_ind_por_ano <- list(
  prop_summary = prop_summary,
  estrato_wide = estrato_wide,
  dp_orientacao = dp_orientacao,
  dp_estrato_sup_prop = dp_estrato_sup_prop,
  indprod = indprod
)

list_ind_por_quadri <-list(
  ppg_key = ppg_key,
  destaques_mark = destaques_mark,
  indprod_disc = indprod_disc,
  docente_fractional_summary = docente_fractional_summary,
  indprod_quadri = indprod_quadri
)



df_ind_por_ano <- reduce(
  list_ind_por_ano,
  ~ left_join(.x, .y, by = c("Cod PPG", "Ano base"))
)

df_ind_por_quadri <- reduce(
  list_ind_por_quadri,
  ~ left_join(.x, .y, by = c("Cod PPG"))
)

df_ind_ano_quadri <- left_join(df_ind_por_ano, df_ind_por_quadri, by = "Cod PPG")


ppg_year_key <- programa |> distinct(`Ano base`, `Cod PPG`) 


final_df <- programa |> left_join(df_ind_ano_quadri, 
                                   by = c("Cod PPG", "Ano base")) |>
  select(nomes_var$var) |>
  arrange(desc(`INDProd Artigo_sum_per_year`), `Cod PPG`,
               `Cod PPG`, desc(`Ano base`)) |>
  mutate(across(contains("destaque"), ~ case_when(
    . == "Muito bom" ~ "MB",
    . == "Bom" ~ "B",
    . == "Regular" ~ "R",
    . == "Fraco" ~ "F",
    . == "Insuficiente ou não aderente" ~ "I",
    TRUE ~ . 
  ))) |>
  mutate(across(where(is.logical), as.numeric))

write_csv(final_df, file = "final_df.csv")