Files
2026-09-07 18:44:32 -03:00

94 lines
4.2 KiB
Python

"""
7-Dimension Scoring Engine with Knockout Criterion for EFINTEL Talent Pool.
"""
from decimal import Decimal, ROUND_HALF_UP
from datetime import date, timedelta
from typing import Dict, Any
class TalentScoringEngine:
# 7-Dimension Official Weighting
WEIGHT_CASE_STUDY = Decimal('0.25') # 25% (Knockout if < 70)
WEIGHT_PORTFOLIO = Decimal('0.15') # 15%
WEIGHT_TECH_SPECIFIC = Decimal('0.15') # 15%
WEIGHT_CARDINAL_SKILLS = Decimal('0.15') # 15%
WEIGHT_EXPERIENCE = Decimal('0.10') # 10%
WEIGHT_PRINCIPLES = Decimal('0.10') # 10%
WEIGHT_INNOVATION = Decimal('0.10') # 10%
KNOCKOUT_THRESHOLD = Decimal('70.0')
APPROVAL_THRESHOLD = Decimal('80.0')
RESERVE_THRESHOLD = Decimal('65.0')
VALIDITY_DAYS = 365
@classmethod
def evaluate(
cls,
dim_case_study: Decimal,
dim_portfolio: Decimal,
dim_tech_specific: Decimal,
dim_cardinal_skills: Decimal,
dim_experience: Decimal,
dim_principles_safety: Decimal,
dim_innovation_rndi: Decimal,
evaluation_date: date = None
) -> Dict[str, Any]:
"""
Calculates weighted 7D score, evaluates Knockout condition, determines status and validity.
"""
d1 = Decimal(str(dim_case_study or 0))
d2 = Decimal(str(dim_portfolio or 0))
d3 = Decimal(str(dim_tech_specific or 0))
d4 = Decimal(str(dim_cardinal_skills or 0))
d5 = Decimal(str(dim_experience or 0))
d6 = Decimal(str(dim_principles_safety or 0))
d7 = Decimal(str(dim_innovation_rndi or 0))
# Check Knockout condition on Dimension 1 (Caso Práctico / Prueba Técnica)
is_knockout = d1 < cls.KNOCKOUT_THRESHOLD
# Calculate weighted total
weighted_score = (
(d1 * cls.WEIGHT_CASE_STUDY) +
(d2 * cls.WEIGHT_PORTFOLIO) +
(d3 * cls.WEIGHT_TECH_SPECIFIC) +
(d4 * cls.WEIGHT_CARDINAL_SKILLS) +
(d5 * cls.WEIGHT_EXPERIENCE) +
(d6 * cls.WEIGHT_PRINCIPLES) +
(d7 * cls.WEIGHT_INNOVATION)
).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
# Determine Final Result Status
if is_knockout:
result_status = 'DESCARTADO'
verdict_message = f"Descartado por Criterio Knockout: Caso Práctico ({d1}/100) inferior al mínimo aprobatorio de {cls.KNOCKOUT_THRESHOLD} puntos."
elif weighted_score >= cls.APPROVAL_THRESHOLD:
result_status = 'APROBADO_CARTERA'
verdict_message = f"¡Aprobado en Cartera de Especialistas! Puntaje de {weighted_score}/100 superior al umbral de excelencia ({cls.APPROVAL_THRESHOLD})."
elif weighted_score >= cls.RESERVE_THRESHOLD:
result_status = 'EN_RESERVA'
verdict_message = f"Calificado en Banco de Reserva ({weighted_score}/100). Cumple estándares operacionales para proyectos secundarios o convocatorias de contingencia."
else:
result_status = 'DESCARTADO'
verdict_message = f"Descartado: Puntaje ponderado ({weighted_score}/100) no alcanza el umbral mínimo de corte ({cls.RESERVE_THRESHOLD})."
eval_date = evaluation_date or date.today()
valid_until = eval_date + timedelta(days=cls.VALIDITY_DAYS)
return {
'weighted_score': weighted_score,
'is_knockout': is_knockout,
'result_status': result_status,
'verdict_message': verdict_message,
'valid_until': valid_until,
'breakdown': {
'case_study_weighted': (d1 * cls.WEIGHT_CASE_STUDY).quantize(Decimal('0.01')),
'portfolio_weighted': (d2 * cls.WEIGHT_PORTFOLIO).quantize(Decimal('0.01')),
'tech_specific_weighted': (d3 * cls.WEIGHT_TECH_SPECIFIC).quantize(Decimal('0.01')),
'cardinal_skills_weighted': (d4 * cls.WEIGHT_CARDINAL_SKILLS).quantize(Decimal('0.01')),
'experience_weighted': (d5 * cls.WEIGHT_EXPERIENCE).quantize(Decimal('0.01')),
'principles_weighted': (d6 * cls.WEIGHT_PRINCIPLES).quantize(Decimal('0.01')),
'innovation_weighted': (d7 * cls.WEIGHT_INNOVATION).quantize(Decimal('0.01')),
}
}