Adiciona suporte ao Bloco B (Coordenacao PPG) e melhora tooltips
- Adiciona Bloco B no ConsultorCard com formula e detalhes - Ajusta calculo de pontuacao total para incluir Bloco B - Melhora tooltips com informacoes de teto e calculo detalhado - Ajusta routes.py para preencher blocos corretamente - Adiciona bloco_b no schema de ranking
This commit is contained in:
@@ -157,14 +157,44 @@ def _consultor_resumo_from_ranking(c):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# Ajusta pontuação detalhada para refletir os valores atuais do ranking (incluindo COMPONENTE_B),
|
||||||
|
# já que o JSON pode ter sido gerado antes do job de preenchimento do Componente B.
|
||||||
|
pontuacao_total = float(c.pontuacao_total or 0)
|
||||||
|
bloco_a = float(c.componente_a or 0)
|
||||||
|
bloco_b = float(c.componente_b or 0)
|
||||||
|
bloco_c = float(c.componente_c or 0)
|
||||||
|
bloco_d = float(c.componente_d or 0)
|
||||||
|
|
||||||
|
if isinstance(pontuacao, dict):
|
||||||
|
pontuacao_ajustada = dict(pontuacao)
|
||||||
|
else:
|
||||||
|
pontuacao_ajustada = {}
|
||||||
|
|
||||||
|
def _ajustar_bloco(chave: str, total: float, letra: str):
|
||||||
|
b = pontuacao_ajustada.get(chave)
|
||||||
|
if isinstance(b, dict):
|
||||||
|
b2 = dict(b)
|
||||||
|
b2["bloco"] = letra
|
||||||
|
b2["total"] = total
|
||||||
|
pontuacao_ajustada[chave] = b2
|
||||||
|
else:
|
||||||
|
pontuacao_ajustada[chave] = {"bloco": letra, "total": total, "atuacoes": []}
|
||||||
|
|
||||||
|
_ajustar_bloco("bloco_a", bloco_a, "A")
|
||||||
|
_ajustar_bloco("bloco_b", bloco_b, "B")
|
||||||
|
_ajustar_bloco("bloco_c", bloco_c, "C")
|
||||||
|
_ajustar_bloco("bloco_d", bloco_d, "D")
|
||||||
|
pontuacao_ajustada["pontuacao_total"] = pontuacao_total
|
||||||
|
|
||||||
return ConsultorRankingResumoSchema(
|
return ConsultorRankingResumoSchema(
|
||||||
id_pessoa=c.id_pessoa,
|
id_pessoa=c.id_pessoa,
|
||||||
nome=c.nome,
|
nome=c.nome,
|
||||||
posicao=c.posicao,
|
posicao=c.posicao,
|
||||||
pontuacao_total=c.pontuacao_total,
|
pontuacao_total=pontuacao_total,
|
||||||
bloco_a=c.componente_a,
|
bloco_a=bloco_a,
|
||||||
bloco_c=c.componente_c,
|
bloco_b=bloco_b,
|
||||||
bloco_d=c.componente_d,
|
bloco_c=bloco_c,
|
||||||
|
bloco_d=bloco_d,
|
||||||
ativo=c.ativo,
|
ativo=c.ativo,
|
||||||
anos_atuacao=c.anos_atuacao,
|
anos_atuacao=c.anos_atuacao,
|
||||||
consultoria=consultoria,
|
consultoria=consultoria,
|
||||||
@@ -176,7 +206,7 @@ def _consultor_resumo_from_ranking(c):
|
|||||||
participacoes=participacoes,
|
participacoes=participacoes,
|
||||||
orientacoes=orientacoes,
|
orientacoes=orientacoes,
|
||||||
membros_banca=membros_banca,
|
membros_banca=membros_banca,
|
||||||
pontuacao=pontuacao,
|
pontuacao=pontuacao_ajustada if pontuacao_ajustada else None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ class ConsultorRankingResumoSchema(BaseModel):
|
|||||||
posicao: Optional[int]
|
posicao: Optional[int]
|
||||||
pontuacao_total: float
|
pontuacao_total: float
|
||||||
bloco_a: float
|
bloco_a: float
|
||||||
|
bloco_b: float
|
||||||
bloco_c: float
|
bloco_c: float
|
||||||
bloco_d: float
|
bloco_d: float
|
||||||
ativo: bool
|
ativo: bool
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ services:
|
|||||||
- "8010:8000"
|
- "8010:8000"
|
||||||
env_file:
|
env_file:
|
||||||
- ./backend/.env
|
- ./backend/.env
|
||||||
|
extra_hosts:
|
||||||
|
- "host.docker.internal:host-gateway"
|
||||||
environment:
|
environment:
|
||||||
- API_HOST=0.0.0.0
|
- API_HOST=0.0.0.0
|
||||||
- API_PORT=8000
|
- API_PORT=8000
|
||||||
|
|||||||
@@ -35,13 +35,15 @@ const CompararModal = ({ consultor1, consultor2, onClose }) => {
|
|||||||
|
|
||||||
const blocoA1 = p1.bloco_a || { total: consultor1.bloco_a || 0 };
|
const blocoA1 = p1.bloco_a || { total: consultor1.bloco_a || 0 };
|
||||||
const blocoA2 = p2.bloco_a || { total: consultor2.bloco_a || 0 };
|
const blocoA2 = p2.bloco_a || { total: consultor2.bloco_a || 0 };
|
||||||
|
const blocoB1 = p1.bloco_b || { total: consultor1.bloco_b || 0 };
|
||||||
|
const blocoB2 = p2.bloco_b || { total: consultor2.bloco_b || 0 };
|
||||||
const blocoC1 = p1.bloco_c || { total: consultor1.bloco_c || 0 };
|
const blocoC1 = p1.bloco_c || { total: consultor1.bloco_c || 0 };
|
||||||
const blocoC2 = p2.bloco_c || { total: consultor2.bloco_c || 0 };
|
const blocoC2 = p2.bloco_c || { total: consultor2.bloco_c || 0 };
|
||||||
const blocoD1 = p1.bloco_d || { total: consultor1.bloco_d || 0 };
|
const blocoD1 = p1.bloco_d || { total: consultor1.bloco_d || 0 };
|
||||||
const blocoD2 = p2.bloco_d || { total: consultor2.bloco_d || 0 };
|
const blocoD2 = p2.bloco_d || { total: consultor2.bloco_d || 0 };
|
||||||
|
|
||||||
const total1 = p1.pontuacao_total || consultor1.pontuacao_total || 0;
|
const total1 = (blocoA1.total || 0) + (blocoB1.total || 0) + (blocoC1.total || 0) + (blocoD1.total || 0);
|
||||||
const total2 = p2.pontuacao_total || consultor2.pontuacao_total || 0;
|
const total2 = (blocoA2.total || 0) + (blocoB2.total || 0) + (blocoC2.total || 0) + (blocoD2.total || 0);
|
||||||
|
|
||||||
const c1 = consultor1.consultoria;
|
const c1 = consultor1.consultoria;
|
||||||
const c2 = consultor2.consultoria;
|
const c2 = consultor2.consultoria;
|
||||||
@@ -97,6 +99,11 @@ const CompararModal = ({ consultor1, consultor2, onClose }) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="comparacao-secao">
|
||||||
|
<h3 style={{ color: 'var(--accent)' }}>B - Coordenacao PPG</h3>
|
||||||
|
{renderLinhaComparacao('Total', blocoB1.total, blocoB2.total, 'var(--accent)')}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="comparacao-secao">
|
<div className="comparacao-secao">
|
||||||
<h3 style={{ color: 'var(--gold)' }}>C - Consultoria</h3>
|
<h3 style={{ color: 'var(--gold)' }}>C - Consultoria</h3>
|
||||||
{renderLinhaComparacao('Total', blocoC1.total, blocoC2.total, 'var(--gold)')}
|
{renderLinhaComparacao('Total', blocoC1.total, blocoC2.total, 'var(--gold)')}
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ const FORMULAS = {
|
|||||||
titulo: 'Coordenacao CAPES',
|
titulo: 'Coordenacao CAPES',
|
||||||
descricao: 'CA=200 | CAJ=150 | CAJ_MP=120 | CAM=100\nTempo: multiplicador por ano\nBonus atualidade + Retorno',
|
descricao: 'CA=200 | CAJ=150 | CAJ_MP=120 | CAM=100\nTempo: multiplicador por ano\nBonus atualidade + Retorno',
|
||||||
},
|
},
|
||||||
|
bloco_b: {
|
||||||
|
titulo: 'Coordenacao PPG',
|
||||||
|
descricao: 'Base=70 | Tempo=5 pts/ano (max 50)\nExtras por programas distintos (max 40)\nBonus por maior nota do programa (max 20)',
|
||||||
|
},
|
||||||
bloco_c: {
|
bloco_c: {
|
||||||
titulo: 'Consultoria',
|
titulo: 'Consultoria',
|
||||||
descricao: 'CONS_ATIVO=150 | CONS_HIST=100 | CONS_FALECIDO=100\nTempo: 5 pts/ano (max 50)\nContinuidade 8a+=15 | Retorno=15',
|
descricao: 'CONS_ATIVO=150 | CONS_HIST=100 | CONS_FALECIDO=100\nTempo: 5 pts/ano (max 50)\nContinuidade 8a+=15 | Retorno=15',
|
||||||
@@ -30,6 +34,28 @@ const PONTOS_BASE = {
|
|||||||
MB_BANCA_POS_DOC: 3, MB_BANCA_TESE: 3, MB_BANCA_DISS: 2,
|
MB_BANCA_POS_DOC: 3, MB_BANCA_TESE: 3, MB_BANCA_DISS: 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Teto oficial por código, conforme documento de critérios (seção 3.x)
|
||||||
|
const TETOS = {
|
||||||
|
// 3.3 Inscrições
|
||||||
|
INSC_AUTOR: { teto: 20, doc: '3.3 Inscrições' },
|
||||||
|
INSC_INST: { teto: 60, doc: '3.3 Inscrições' },
|
||||||
|
// 3.4 Avaliação / Coordenação de Comissão
|
||||||
|
AVAL_COMIS_PREMIO: { teto: 60, doc: '3.4 Avaliação/Comissão' },
|
||||||
|
AVAL_COMIS_GP: { teto: 100, doc: '3.4 Avaliação/Comissão' },
|
||||||
|
COORD_COMIS_PREMIO: { teto: 100, doc: '3.4 Avaliação/Comissão' },
|
||||||
|
COORD_COMIS_GP: { teto: 120, doc: '3.4 Avaliação/Comissão' },
|
||||||
|
// 3.6 Premiações
|
||||||
|
PREMIACAO: { teto: 180, doc: '3.6 Premiações' },
|
||||||
|
PREMIACAO_GP: { teto: 60, doc: '3.6 Premiações' },
|
||||||
|
MENCAO: { teto: 20, doc: '3.6 Premiações' },
|
||||||
|
// 3.7 Participações
|
||||||
|
EVENTO: { teto: 5, doc: '3.7 Participações' },
|
||||||
|
PROJ: { teto: 40, doc: '3.7 Participações' },
|
||||||
|
// 3.5 Bolsas CNPQ (nomes resumidos)
|
||||||
|
BOL_BPQ_SUPERIOR: { teto: 60, doc: '3.5 Bolsas CNPQ' },
|
||||||
|
BOL_BPQ_INTERMEDIARIO: { teto: 100, doc: '3.5 Bolsas CNPQ' },
|
||||||
|
};
|
||||||
|
|
||||||
const ScoreItemWithTooltip = ({ value, label, formula, style }) => (
|
const ScoreItemWithTooltip = ({ value, label, formula, style }) => (
|
||||||
<div className="score-item-wrapper">
|
<div className="score-item-wrapper">
|
||||||
<div className="score-item" style={style}>
|
<div className="score-item" style={style}>
|
||||||
@@ -71,9 +97,10 @@ const ConsultorCard = ({ consultor, highlight, selecionado, onToggleSelecionado
|
|||||||
|
|
||||||
const { consultoria, pontuacao } = consultor;
|
const { consultoria, pontuacao } = consultor;
|
||||||
const blocoA = pontuacao?.bloco_a || { total: consultor.bloco_a || 0 };
|
const blocoA = pontuacao?.bloco_a || { total: consultor.bloco_a || 0 };
|
||||||
|
const blocoB = pontuacao?.bloco_b || { total: consultor.bloco_b || 0 };
|
||||||
const blocoC = pontuacao?.bloco_c || { total: consultor.bloco_c || 0 };
|
const blocoC = pontuacao?.bloco_c || { total: consultor.bloco_c || 0 };
|
||||||
const blocoD = pontuacao?.bloco_d || { total: consultor.bloco_d || 0 };
|
const blocoD = pontuacao?.bloco_d || { total: consultor.bloco_d || 0 };
|
||||||
const pontuacaoTotal = pontuacao?.pontuacao_total || consultor.pontuacao_total || 0;
|
const pontuacaoTotal = (blocoA.total || 0) + (blocoB.total || 0) + (blocoC.total || 0) + (blocoD.total || 0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={cardRef} className={`ranking-card ${expanded ? 'expanded' : ''} ${highlight ? 'highlight' : ''} ${selecionado ? 'selecionado' : ''}`} onClick={() => setExpanded(!expanded)}>
|
<div ref={cardRef} className={`ranking-card ${expanded ? 'expanded' : ''} ${highlight ? 'highlight' : ''} ${selecionado ? 'selecionado' : ''}`} onClick={() => setExpanded(!expanded)}>
|
||||||
@@ -134,6 +161,12 @@ const ConsultorCard = ({ consultor, highlight, selecionado, onToggleSelecionado
|
|||||||
formula={FORMULAS.bloco_a.descricao}
|
formula={FORMULAS.bloco_a.descricao}
|
||||||
style={{ color: blocoA.total > 0 ? 'var(--accent-2)' : 'var(--muted)' }}
|
style={{ color: blocoA.total > 0 ? 'var(--accent-2)' : 'var(--muted)' }}
|
||||||
/>
|
/>
|
||||||
|
<ScoreItemWithTooltip
|
||||||
|
value={blocoB.total}
|
||||||
|
label="BLOCO B"
|
||||||
|
formula={FORMULAS.bloco_b.descricao}
|
||||||
|
style={{ color: blocoB.total > 0 ? 'var(--accent)' : 'var(--muted)' }}
|
||||||
|
/>
|
||||||
<ScoreItemWithTooltip
|
<ScoreItemWithTooltip
|
||||||
value={blocoC.total}
|
value={blocoC.total}
|
||||||
label="BLOCO C"
|
label="BLOCO C"
|
||||||
@@ -151,7 +184,7 @@ const ConsultorCard = ({ consultor, highlight, selecionado, onToggleSelecionado
|
|||||||
<div className="score-item-value">{pontuacaoTotal}</div>
|
<div className="score-item-value">{pontuacaoTotal}</div>
|
||||||
<div className="score-item-label">TOTAL</div>
|
<div className="score-item-label">TOTAL</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="score-tooltip">Bloco A + Bloco C + Bloco D</div>
|
<div className="score-tooltip">Bloco A + Bloco B + Bloco C + Bloco D</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -160,6 +193,10 @@ const ConsultorCard = ({ consultor, highlight, selecionado, onToggleSelecionado
|
|||||||
<BlocoDetalhes titulo="A - Coordenacao CAPES" bloco={blocoA} cor="var(--accent-2)" />
|
<BlocoDetalhes titulo="A - Coordenacao CAPES" bloco={blocoA} cor="var(--accent-2)" />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{(blocoB.total > 0 || (blocoB.atuacoes && blocoB.atuacoes.length > 0)) && (
|
||||||
|
<BlocoDetalhes titulo="B - Coordenacao PPG" bloco={blocoB} cor="var(--accent)" />
|
||||||
|
)}
|
||||||
|
|
||||||
{blocoC.atuacoes && blocoC.atuacoes.length > 0 && (
|
{blocoC.atuacoes && blocoC.atuacoes.length > 0 && (
|
||||||
<BlocoDetalhes titulo="C - Consultoria" bloco={blocoC} cor="var(--gold)" />
|
<BlocoDetalhes titulo="C - Consultoria" bloco={blocoC} cor="var(--gold)" />
|
||||||
)}
|
)}
|
||||||
@@ -270,8 +307,30 @@ const BlocoDetalhes = ({ titulo, bloco, cor }) => (
|
|||||||
<div className="score-item-label">{at.codigo}</div>
|
<div className="score-item-label">{at.codigo}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="score-tooltip">
|
<div className="score-tooltip">
|
||||||
Base: {at.base} | Tempo: {at.tempo} | Bonus: {at.bonus}
|
{(() => {
|
||||||
{at.quantidade > 1 && ` | Qtd: ${at.quantidade}`}
|
const base = at.base || 0;
|
||||||
|
const tempo = at.tempo || 0;
|
||||||
|
const bonus = at.bonus || 0;
|
||||||
|
const bruto = base + tempo + bonus;
|
||||||
|
const meta = TETOS[at.codigo];
|
||||||
|
const capped = bruto !== at.total;
|
||||||
|
const unidade = at.quantidade > 1 ? Math.round(base / at.quantidade) : null;
|
||||||
|
|
||||||
|
const partes = [];
|
||||||
|
partes.push(
|
||||||
|
unidade
|
||||||
|
? `Base ${unidade} x ${at.quantidade} = ${base}`
|
||||||
|
: `Base ${base}`
|
||||||
|
);
|
||||||
|
if (capped) {
|
||||||
|
partes.push(`Bruto ${bruto}`);
|
||||||
|
}
|
||||||
|
if (tempo) partes.push(`Tempo ${tempo}`);
|
||||||
|
if (bonus) partes.push(`Bônus ${bonus}`);
|
||||||
|
if (meta) partes.push(`Teto ${meta.teto}`);
|
||||||
|
partes.push(capped && meta ? `Total ${at.total} (teto)` : `Total ${at.total}`);
|
||||||
|
return partes.join(" | ");
|
||||||
|
})()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ export const rankingService = {
|
|||||||
posicao: c.posicao,
|
posicao: c.posicao,
|
||||||
pontuacao_total: c.pontuacao_total,
|
pontuacao_total: c.pontuacao_total,
|
||||||
bloco_a: c.bloco_a,
|
bloco_a: c.bloco_a,
|
||||||
|
bloco_b: c.bloco_b,
|
||||||
bloco_c: c.bloco_c,
|
bloco_c: c.bloco_c,
|
||||||
bloco_d: c.bloco_d,
|
bloco_d: c.bloco_d,
|
||||||
ativo: c.ativo,
|
ativo: c.ativo,
|
||||||
@@ -52,6 +53,7 @@ export const rankingService = {
|
|||||||
pontuacao: c.pontuacao || {
|
pontuacao: c.pontuacao || {
|
||||||
pontuacao_total: c.pontuacao_total,
|
pontuacao_total: c.pontuacao_total,
|
||||||
bloco_a: { total: c.bloco_a, atuacoes: [] },
|
bloco_a: { total: c.bloco_a, atuacoes: [] },
|
||||||
|
bloco_b: { total: c.bloco_b, atuacoes: [] },
|
||||||
bloco_c: { total: c.bloco_c, atuacoes: [] },
|
bloco_c: { total: c.bloco_c, atuacoes: [] },
|
||||||
bloco_d: { total: c.bloco_d, atuacoes: [] },
|
bloco_d: { total: c.bloco_d, atuacoes: [] },
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user