fix(frontend): alinhar insights e criterios com planilha oficial

- Corrigir gerarInsights() removendo conceitos inexistentes (TETOS_BLOCO,
  "Destaque em Coordenação CAPES", aproveitamento % do teto de bloco)
- Adicionar valores corretos de bônus conforme Aba 4 do Excel oficial
- Remover "max 300" do Bloco C (não existe teto de bloco na especificação)
- Remover PRES_CAM do Bloco D (código inexistente na planilha oficial)
This commit is contained in:
Frederico Castro
2025-12-23 22:48:48 -03:00
parent ab1cb1ba8c
commit 73ea0943ba
2 changed files with 23 additions and 27 deletions

View File

@@ -878,8 +878,6 @@ const PONTOS_BASE = {
EVENTO: 1, PROJ: 10, EVENTO: 1, PROJ: 10,
}; };
const TETOS_BLOCO = { A: 450, B: 230, C: 500, D: 300 };
const gerarInsights = (consultor, totalConsultores) => { const gerarInsights = (consultor, totalConsultores) => {
const insights = []; const insights = [];
const posicao = consultor.posicao || consultor.rank || 0; const posicao = consultor.posicao || consultor.rank || 0;
@@ -905,10 +903,10 @@ const gerarInsights = (consultor, totalConsultores) => {
} }
const blocos = [ const blocos = [
{ nome: 'Coordenação CAPES', letra: 'A', valor: blocoA, teto: TETOS_BLOCO.A }, { nome: 'Coordenação CAPES', letra: 'A', valor: blocoA },
{ nome: 'Consultoria', letra: 'B', valor: blocoB, teto: TETOS_BLOCO.B }, { nome: 'Consultoria', letra: 'B', valor: blocoB },
{ nome: 'Avaliações/Premiações', letra: 'C', valor: blocoC, teto: TETOS_BLOCO.C }, { nome: 'Avaliações/Premiações', letra: 'C', valor: blocoC },
{ nome: 'Indicadores', letra: 'D', valor: blocoD, teto: TETOS_BLOCO.D }, { nome: 'Indicadores', letra: 'D', valor: blocoD },
]; ];
const blocosAtivos = blocos.filter(b => b.valor > 0); const blocosAtivos = blocos.filter(b => b.valor > 0);
@@ -916,7 +914,7 @@ const gerarInsights = (consultor, totalConsultores) => {
const maiorBloco = blocosAtivos.reduce((a, b) => a.valor > b.valor ? a : b); const maiorBloco = blocosAtivos.reduce((a, b) => a.valor > b.valor ? a : b);
const pct = Math.round(maiorBloco.valor / pontuacao * 100); const pct = Math.round(maiorBloco.valor / pontuacao * 100);
if (pct >= 50) { if (pct >= 50) {
insights.push({ icone: '📊', texto: `${pct}% da pontuação vem de ${maiorBloco.nome} (Bloco ${maiorBloco.letra})` }); insights.push({ icone: '📊', texto: `${pct}% da pontuação vem de ${maiorBloco.nome}` });
} }
} }
@@ -924,48 +922,48 @@ const gerarInsights = (consultor, totalConsultores) => {
const coordAtiva = coords.find(c => c.ativo ?? !c.fim); const coordAtiva = coords.find(c => c.ativo ?? !c.fim);
if (coordAtiva) { if (coordAtiva) {
const labels = { CA: 'Coordenador de Área', CAJ: 'Coordenador Adjunto', CAJ_MP: 'Coord. Adjunto MP', CAM: 'Câmara Temática' }; const labels = { CA: 'Coordenador de Área', CAJ: 'Coordenador Adjunto', CAJ_MP: 'Coord. Adjunto MP', CAM: 'Câmara Temática' };
insights.push({ icone: '🎯', texto: `${labels[coordAtiva.codigo] || coordAtiva.codigo} em exercício` }); const bonusAtual = { CA: 30, CAJ: 20, CAJ_MP: 15, CAM: 20 };
insights.push({ icone: '🎯', texto: `${labels[coordAtiva.codigo] || coordAtiva.codigo} em exercício (+${bonusAtual[coordAtiva.codigo] || 0} bônus atualidade)` });
} else if (coords.length > 0) { } else if (coords.length > 0) {
insights.push({ icone: '📜', texto: `Histórico de ${coords.length} coordenação(ões) CAPES` }); insights.push({ icone: '📜', texto: `Histórico de ${coords.length} coordenação(ões) CAPES` });
} }
if (blocoA >= 300) {
insights.push({ icone: '🌟', texto: 'Destaque em Coordenação CAPES' });
}
const consultoria = consultor.consultoria || {}; const consultoria = consultor.consultoria || {};
if (consultor.ativo && consultoria.anos_consecutivos >= 8) { if (consultor.ativo && consultoria.anos_consecutivos >= 8) {
insights.push({ icone: '💎', texto: `${consultoria.anos_consecutivos} anos consecutivos de consultoria (+bônus continuidade)` }); insights.push({ icone: '💎', texto: `${consultoria.anos_consecutivos} anos consecutivos (+20 bônus continuidade)` });
} else if (consultor.ativo && consultoria.anos_consecutivos >= 5) { } else if (consultoria.anos_consecutivos >= 3) {
insights.push({ icone: '🔷', texto: `${consultoria.anos_consecutivos} anos consecutivos de consultoria` }); insights.push({ icone: '🔷', texto: `${consultoria.anos_consecutivos} anos consecutivos de consultoria` });
} }
if (consultoria.retornos > 0) { if (consultoria.retornos > 0) {
insights.push({ icone: '🔄', texto: `Retorno à consultoria (+bônus reativação)` }); const bonusRetorno = consultor.ativo ? 15 : 20;
insights.push({ icone: '🔄', texto: `Retorno à consultoria (+${bonusRetorno} bônus reativação)` });
} }
const premiacoes = consultor.premiacoes || []; const premiacoes = consultor.premiacoes || [];
const gps = premiacoes.filter(p => p.codigo === 'PREMIACAO_GP_AUTOR'); const gps = premiacoes.filter(p => p.codigo === 'PREMIACAO_GP_AUTOR');
const premios = premiacoes.filter(p => p.codigo === 'PREMIACAO_AUTOR'); const premios = premiacoes.filter(p => p.codigo === 'PREMIACAO_AUTOR');
const mencoes = premiacoes.filter(p => p.codigo === 'MENCAO_AUTOR');
if (gps.length > 0) { if (gps.length > 0) {
insights.push({ icone: '🏆', texto: `${gps.length}x Grande Prêmio CAPES` }); insights.push({ icone: '🏆', texto: `${gps.length}x Grande Prêmio CAPES (base 100 pts cada)` });
} else if (premios.length > 0) { }
insights.push({ icone: '🥇', texto: `${premios.length}x Prêmio CAPES` }); if (premios.length > 0) {
insights.push({ icone: '🥇', texto: `${premios.length}x Prêmio CAPES (base 50 pts cada)` });
}
if (mencoes.length > 0) {
insights.push({ icone: '🎖️', texto: `${mencoes.length}x Menção Honrosa (base 30 pts cada)` });
} }
const anos = consultor.anos_atuacao || 0; const anos = consultor.anos_atuacao || 0;
if (anos >= 15) { if (anos >= 15) {
insights.push({ icone: '👑', texto: `${anos} anos de contribuição ao SNPG` }); insights.push({ icone: '👑', texto: `${anos} anos de contribuição ao SNPG` });
} else if (anos >= 10) { } else if (anos >= 10) {
insights.push({ icone: '🎖️', texto: `Veterano com ${anos} anos de atuação` }); insights.push({ icone: '🏅', texto: `Veterano com ${anos} anos de atuação` });
} }
blocosAtivos.forEach(b => { if (blocoA > 0 && blocoB > 0 && blocoC > 0) {
const aproveitamento = Math.round(b.valor / b.teto * 100); insights.push({ icone: '🌟', texto: 'Perfil diversificado: coordenação + consultoria + avaliações' });
if (aproveitamento >= 80) {
insights.push({ icone: '✅', texto: `${b.nome}: ${aproveitamento}% do teto (${b.valor}/${b.teto})` });
} }
});
if (insights.length === 0) { if (insights.length === 0) {
insights.push({ icone: '📋', texto: `Pontuação total: ${pontuacao} pontos` }); insights.push({ icone: '📋', texto: `Pontuação total: ${pontuacao} pontos` });

View File

@@ -74,7 +74,6 @@ const Header = ({ total }) => {
<div className="criteria-section bloco-c wide"> <div className="criteria-section bloco-c wide">
<div className="section-header"> <div className="section-header">
<h4>C - Premiacoes, Avaliacoes, Inscricoes</h4> <h4>C - Premiacoes, Avaliacoes, Inscricoes</h4>
<span className="max-pts">max 300</span>
</div> </div>
<div className="table-columns"> <div className="table-columns">
<table className="criteria-table selos-table"> <table className="criteria-table selos-table">
@@ -179,7 +178,6 @@ const Header = ({ total }) => {
<tr><td>PROJ</td><td>10</td><td>30</td><td><span className="selo-legenda selo-proj">📁</span></td></tr> <tr><td>PROJ</td><td>10</td><td>30</td><td><span className="selo-legenda selo-proj">📁</span></td></tr>
<tr><td>EVENTO</td><td>1</td><td>5</td><td><span className="selo-legenda selo-evento">📅</span></td></tr> <tr><td>EVENTO</td><td>1</td><td>5</td><td><span className="selo-legenda selo-evento">📅</span></td></tr>
<tr><td>PPG_COORD</td><td>-</td><td>-</td><td><span className="selo-legenda selo-coord">🎓</span></td></tr> <tr><td>PPG_COORD</td><td>-</td><td>-</td><td><span className="selo-legenda selo-coord">🎓</span></td></tr>
<tr><td>PRES_CAM</td><td>-</td><td>-</td><td><span className="selo-legenda selo-camara">👑</span></td></tr>
</tbody> </tbody>
</table> </table>
</div> </div>