iteracion 2
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
from .rubric import TalentScoringEngine
|
||||
|
||||
__all__ = ['TalentScoringEngine']
|
||||
@@ -0,0 +1,93 @@
|
||||
"""
|
||||
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')),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user