FCT / services /personality_module.py
Parthnuwal7
Adding analytical content
3d015cd
"""Personality Module - Big Five Trait Scoring"""
import numpy as np
from typing import Dict, Tuple
class PersonalityModule:
"""Scores personality based on Big Five traits"""
def __init__(self):
# Map questions to traits (reversed questions need inverse scoring)
self.trait_mapping = {
'openness': ['p_q1', 'p_q3', 'p_q4'],
'openness_r': ['p_q2'], # Reversed
'conscientiousness': ['p_q5', 'p_q7', 'p_q8'],
'conscientiousness_r': ['p_q6'], # Reversed
'extraversion': ['p_q9', 'p_q11', 'p_q12'],
'extraversion_r': ['p_q10'], # Reversed
'agreeableness': ['p_q13', 'p_q15', 'p_q16'],
'agreeableness_r': ['p_q14'], # Reversed
'stability': ['p_q17', 'p_q19', 'p_q20'],
'stability_r': ['p_q18'] # Reversed
}
# Weights for employability (some traits matter more)
self.trait_weights = {
'openness': 0.20,
'conscientiousness': 0.30,
'extraversion': 0.20,
'agreeableness': 0.15,
'stability': 0.15
}
def score(self, responses: Dict[str, int]) -> Tuple[float, float, Dict]:
"""
Calculate personality score from 20 questions
Returns: (score, confidence, trait_scores)
"""
trait_scores = {}
# Calculate each trait score
for trait in ['openness', 'conscientiousness', 'extraversion', 'agreeableness', 'stability']:
# Get normal questions
normal_qs = self.trait_mapping[trait]
reversed_qs = self.trait_mapping[f'{trait}_r']
# Calculate average for this trait
scores = []
# Normal questions: higher = better
for q in normal_qs:
if q in responses:
scores.append((responses[q] - 1) / 4.0) # Normalize 1-5 to 0-1
# Reversed questions: lower = better
for q in reversed_qs:
if q in responses:
scores.append((5 - responses[q]) / 4.0) # Invert and normalize
if scores:
trait_scores[trait] = np.mean(scores)
else:
trait_scores[trait] = 0.5 # Neutral if missing
# Calculate overall personality score
personality_score = sum(
trait_scores[trait] * self.trait_weights[trait]
for trait in trait_scores.keys()
)
# Calculate confidence based on question completion
total_questions = 20
answered_questions = len(responses)
confidence = answered_questions / total_questions
return personality_score, confidence, trait_scores
def explain(self, trait_scores: Dict) -> Dict:
"""Generate explanation for personality scores"""
explanations = {
'top_strengths': [],
'areas_for_growth': []
}
# Sort traits by score
sorted_traits = sorted(trait_scores.items(), key=lambda x: x[1], reverse=True)
# Top 2 strengths
for trait, score in sorted_traits[:2]:
if score > 0.6:
explanations['top_strengths'].append({
'trait': trait.capitalize(),
'score': round(score, 2),
'description': self._get_trait_description(trait, score)
})
# Bottom 2 areas for growth
for trait, score in sorted_traits[-2:]:
if score < 0.5:
explanations['areas_for_growth'].append({
'trait': trait.capitalize(),
'score': round(score, 2),
'description': self._get_trait_description(trait, score)
})
return explanations
def _get_trait_description(self, trait: str, score: float) -> str:
"""Get description of trait"""
descriptions = {
'openness': {
'high': "Highly creative, curious, and open to new experiences",
'low': "Prefers routine and traditional approaches"
},
'conscientiousness': {
'high': "Very organized, reliable, and goal-oriented",
'low': "May benefit from improved organization and planning"
},
'extraversion': {
'high': "Energetic, sociable, and thrives in team environments",
'low': "Prefers independent work and smaller groups"
},
'agreeableness': {
'high': "Cooperative, empathetic, and team-oriented",
'low': "Independent thinker, comfortable with competition"
},
'stability': {
'high': "Emotionally stable, handles stress well",
'low': "May experience stress in high-pressure situations"
}
}
level = 'high' if score > 0.6 else 'low'
return descriptions.get(trait, {}).get(level, f"{trait} score: {score:.2f}")