"""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}")