Technology Stack Comparator - Main comparison engine with weighted scoring.
Provides comprehensive technology comparison with customizable weighted criteria,
feature matrices, and intelligent recommendation generation.
from typing import Dict, List, Any, Optional, Tuple
"""Main comparison engine for technology stack evaluation."""
# Feature categories for evaluation
# Default weights if not provided
"developer_experience": 20,
"enterprise_readiness": 5
def __init__(self, comparison_data: Dict[str, Any]):
Initialize comparator with comparison data.
comparison_data: Dictionary containing technologies to compare and criteria
self.technologies = comparison_data.get('technologies', [])
self.use_case = comparison_data.get('use_case', 'general')
self.priorities = comparison_data.get('priorities', {})
self.weights = self._normalize_weights(comparison_data.get('weights', {}))
def _normalize_weights(self, custom_weights: Dict[str, float]) -> Dict[str, float]:
Normalize weights to sum to 100.
custom_weights: User-provided weights
Normalized weights dictionary
weights = self.DEFAULT_WEIGHTS.copy()
# Override with custom weights
weights.update(custom_weights)
total = sum(weights.values())
return self.DEFAULT_WEIGHTS
return {k: (v / total) * 100 for k, v in weights.items()}
def score_technology(self, tech_name: str, tech_data: Dict[str, Any]) -> Dict[str, float]:
Score a single technology across all criteria.
tech_name: Name of technology
tech_data: Technology feature and metric data
Dictionary of category scores (0-100 scale)
for category in self.FEATURE_CATEGORIES:
# Get raw score from tech data (0-100 scale)
raw_score = tech_data.get(category, {}).get('score', 50.0)
# Apply use-case specific adjustments
adjusted_score = self._adjust_for_use_case(category, raw_score, tech_name)
scores[category] = min(100.0, max(0.0, adjusted_score))
def _adjust_for_use_case(self, category: str, score: float, tech_name: str) -> float:
Apply use-case specific adjustments to scores.
category: Feature category
tech_name: Technology name
# Use case specific bonuses/penalties
'performance': 1.1, # 10% bonus for real-time use cases
'enterprise_readiness': 1.2, # 20% bonus
'developer_experience': 1.15,
# Determine use case type
use_case_lower = self.use_case.lower()
for uc_key in adjustments.keys():
if uc_key in use_case_lower:
# Apply adjustment if applicable
if use_case_type and category in adjustments[use_case_type]:
multiplier = adjustments[use_case_type][category]
return score * multiplier
def calculate_weighted_score(self, category_scores: Dict[str, float]) -> float:
Calculate weighted total score.
category_scores: Dictionary of category scores
Weighted total score (0-100 scale)
for category, score in category_scores.items():
weight = self.weights.get(category, 0.0) / 100.0 # Convert to decimal
def compare_technologies(self, tech_data_list: List[Dict[str, Any]]) -> Dict[str, Any]:
Compare multiple technologies and generate recommendation.
tech_data_list: List of technology data dictionaries
Comparison results with scores and recommendation
for tech_data in tech_data_list:
tech_name = tech_data.get('name', 'Unknown')
category_scores = self.score_technology(tech_name, tech_data)
weighted_score = self.calculate_weighted_score(category_scores)
tech_scores[tech_name] = {
'category_scores': category_scores,
'weighted_total': weighted_score,
'strengths': self._identify_strengths(category_scores),
'weaknesses': self._identify_weaknesses(category_scores)
results['technologies'] = tech_scores
# Generate recommendation
results['recommendation'], results['confidence'] = self._generate_recommendation(tech_scores)
results['decision_factors'] = self._extract_decision_factors(tech_scores)
results['comparison_matrix'] = self._build_comparison_matrix(tech_scores)
def _identify_strengths(self, category_scores: Dict[str, float], threshold: float = 75.0) -> List[str]:
Identify strength categories (scores above threshold).
category_scores: Category scores dictionary
threshold: Score threshold for strength identification
List of strength categories
category for category, score in category_scores.items()
def _identify_weaknesses(self, category_scores: Dict[str, float], threshold: float = 50.0) -> List[str]:
Identify weakness categories (scores below threshold).
category_scores: Category scores dictionary
threshold: Score threshold for weakness identification
List of weakness categories
category for category, score in category_scores.items()
def _generate_recommendation(self, tech_scores: Dict[str, Dict[str, Any]]) -> Tuple[str, float]:
Generate recommendation and confidence level.
tech_scores: Technology scores dictionary
Tuple of (recommended_technology, confidence_score)
return "Insufficient data", 0.0
# Sort by weighted total score
key=lambda x: x[1]['weighted_total'],
top_tech = sorted_techs[0][0]
top_score = sorted_techs[0][1]['weighted_total']
# Calculate confidence based on score gap
if len(sorted_techs) > 1:
second_score = sorted_techs[1][1]['weighted_total']
score_gap = top_score - second_score
# Confidence increases with score gap
# 0-5 gap: low confidence
# 5-15 gap: medium confidence
# 15+ gap: high confidence
confidence = 40.0 + (score_gap * 2) # 40-50%
confidence = 50.0 + (score_gap - 5) * 2 # 50-70%
confidence = 70.0 + min(score_gap - 15, 30) # 70-100%
confidence = 100.0 # Only one option
return top_tech, min(100.0, confidence)
def _extract_decision_factors(self, tech_scores: Dict[str, Dict[str, Any]]) -> List[Dict[str, Any]]:
Extract key decision factors from comparison.
tech_scores: Technology scores dictionary
List of decision factors with importance weights
# Get top weighted categories
for category, weight in sorted_weights:
# Get scores for this category across all techs
tech: scores['category_scores'].get(category, 0.0)
for tech, scores in tech_scores.items()
best_tech = max(category_scores.items(), key=lambda x: x[1])
'importance': f"{weight:.1f}%",
'best_performer': best_tech[0],
def _build_comparison_matrix(self, tech_scores: Dict[str, Dict[str, Any]]) -> List[Dict[str, Any]]:
Build comparison matrix for display.
tech_scores: Technology scores dictionary
List of comparison matrix rows
for category in self.FEATURE_CATEGORIES:
'weight': f"{self.weights.get(category, 0):.1f}%",
for tech_name, scores in tech_scores.items():
category_score = scores['category_scores'].get(category, 0.0)
row['scores'][tech_name] = f"{category_score:.1f}"
# Add weighted totals row
'category': 'WEIGHTED TOTAL',
for tech_name, scores in tech_scores.items():
totals_row['scores'][tech_name] = f"{scores['weighted_total']:.1f}"
matrix.append(totals_row)
def generate_pros_cons(self, tech_name: str, tech_scores: Dict[str, Any]) -> Dict[str, List[str]]:
Generate pros and cons for a technology.
tech_name: Technology name
tech_scores: Technology scores dictionary
Dictionary with 'pros' and 'cons' lists
category_scores = tech_scores['category_scores']
strengths = tech_scores['strengths']
weaknesses = tech_scores['weaknesses']
# Generate pros from strengths
for strength in strengths[:3]: # Top 3
score = category_scores[strength]
pros.append(f"Excellent {strength.replace('_', ' ')} (score: {score:.1f}/100)")
# Generate cons from weaknesses
for weakness in weaknesses[:3]: # Top 3
score = category_scores[weakness]
cons.append(f"Weaker {weakness.replace('_', ' ')} (score: {score:.1f}/100)")
# Add generic pros/cons if not enough specific ones
pros.append(f"Balanced performance across all categories")
cons.append(f"No significant weaknesses identified")
return {'pros': pros, 'cons': cons}