fix: Corrige cálculo de pontuação da nota do PPG no Componente B

Mudanças:
- Implementa escala correta de nota: 7=20, 6=15, 5=10, 4=5, 3=0
- Usa MAIOR nota entre os programas coordenados
- Adiciona documentação detalhada no método
- Corrige extras para programas adicionais (só conta se > 1)

Conforme especificação técnica oficial CAPES
This commit is contained in:
Frederico Castro
2025-12-10 04:24:24 -03:00
parent e11cdcd083
commit 57ef5a763a

View File

@@ -103,27 +103,54 @@ class CalculadorPontuacao:
@staticmethod
def calcular_componente_b(coordenacoes: List[CoordenacaoPrograma]) -> ComponentePontuacao:
"""
Calcula pontuação do Componente B (Coordenação de Programa PPG).
Regras (máximo 180 pts):
- Base: 70 pts por ser coordenador
- Tempo: 5 pts/ano (máx 50)
- Programas adicionais: 20 pts/programa (máx 40)
- Nota do PPG: usar MAIOR nota (7=20, 6=15, 5=10, 4=5, 3=0)
"""
if not coordenacoes:
return ComponentePontuacao(base=0, tempo=0, extras=0, bonus=0)
# Base: 70 pts por ser coordenador
base = 70
# Tempo: 5 pts/ano (máx 50)
anos_totais = sum(c.periodo.anos_completos(datetime.now()) for c in coordenacoes)
tempo = min(int(anos_totais * 5), 50)
# Programas adicionais: 20 pts/programa extra (máx 40)
programas_distintos = len({c.id_programa for c in coordenacoes})
extras = min((programas_distintos - 1) * 20, 40)
extras = min((programas_distintos - 1) * 20, 40) if programas_distintos > 1 else 0
nota_bonus = 0
# Nota do PPG: usar MAIOR nota entre os programas
# Escala: 7=20, 6=15, 5=10, 4=5, 3=0
maior_nota = 0
for c in coordenacoes:
try:
nota_num = float(c.nota_ppg)
if nota_num >= 0:
nota_bonus = 20
break
nota_str = str(c.nota_ppg).strip()
# Trata notas válidas (3-7 ou A para programas novos)
if nota_str in ['7']:
maior_nota = max(maior_nota, 7)
elif nota_str in ['6']:
maior_nota = max(maior_nota, 6)
elif nota_str in ['5']:
maior_nota = max(maior_nota, 5)
elif nota_str in ['4']:
maior_nota = max(maior_nota, 4)
elif nota_str in ['3']:
maior_nota = max(maior_nota, 3)
except Exception:
continue
return ComponentePontuacao(base=base, tempo=tempo, extras=extras, bonus=nota_bonus)
# Mapeia nota para pontos
mapa_nota = {7: 20, 6: 15, 5: 10, 4: 5, 3: 0}
bonus = mapa_nota.get(maior_nota, 0)
return ComponentePontuacao(base=base, tempo=tempo, extras=extras, bonus=bonus)
@staticmethod
def calcular_componente_c(consultoria: Consultoria) -> ComponentePontuacao: