""" Understanding Scorer Module Calculates final understanding scores from analysis results """ from typing import Dict, Optional class UnderstandingScorer: def __init__(self): # Scoring weights - adjusted these a few times based on testing # coverage is weighted highest because it's most reliable self.weights = { 'consistency': 0.25, 'coverage': 0.35, 'stability': 0.25, 'assumptions': 0.15 } def calculate_scores( self, consistency_result: Dict, coverage_result: Dict, stability_result: Optional[Dict] ) -> Dict: """ Calculate multi-dimensional understanding scores Returns: { 'overall': float (0-100), 'consistency': float (0-100), 'coverage': float (0-100), 'stability': float (0-100), 'assumptions': float (0-100) } """ # Extract individual scores consistency_score = consistency_result.get('consistency_score', 0) coverage_score = coverage_result.get('coverage_score', 0) stability_score = stability_result.get('stability_score', 100) if stability_result else 100 # Calculate assumption completeness score # Based on whether key assumptions are made explicit assumptions_score = self._calculate_assumption_score( coverage_result=coverage_result, consistency_result=consistency_result ) # Calculate weighted overall score overall_score = ( consistency_score * self.weights['consistency'] + coverage_score * self.weights['coverage'] + stability_score * self.weights['stability'] + assumptions_score * self.weights['assumptions'] ) return { 'overall': round(overall_score, 1), 'consistency': round(consistency_score, 1), 'coverage': round(coverage_score, 1), 'stability': round(stability_score, 1), 'assumptions': round(assumptions_score, 1) } def _calculate_assumption_score( self, coverage_result: Dict, consistency_result: Dict ) -> float: """ Calculate assumption completeness score High score = explicit about assumptions, boundary conditions, limitations Low score = makes implicit assumptions without stating them """ # Simple heuristic for now - basically if consistency and coverage are good, # assumptions are probably okay. Not perfect but works decently. consistency_score = consistency_result.get('consistency_score', 0) coverage_score = coverage_result.get('coverage_score', 0) # Missing concepts indicate unstated assumptions missing_count = len(coverage_result.get('missing_concepts', [])) # Contradictions indicate conflicting implicit assumptions contradiction_count = len(consistency_result.get('contradictions', [])) # Base score on coverage and consistency base_score = (consistency_score + coverage_score) / 2 # Penalize for missing concepts (unstated prerequisites) missing_penalty = min(30, missing_count * 10) # Penalize for contradictions (conflicting assumptions) contradiction_penalty = min(20, contradiction_count * 15) final_score = base_score - missing_penalty - contradiction_penalty return max(0, min(100, final_score))