""" Total Cost of Ownership (TCO) Calculator. Calculates comprehensive TCO including licensing, hosting, developer productivity, scaling costs, and hidden costs over multi-year projections. """ from typing import Dict, List, Any, Optional import json class TCOCalculator: """Calculate Total Cost of Ownership for technology stacks.""" def __init__(self, tco_data: Dict[str, Any]): """ Initialize TCO calculator with cost parameters. Args: tco_data: Dictionary containing cost parameters and projections """ self.technology = tco_data.get('technology', 'Unknown') self.team_size = tco_data.get('team_size', 5) self.timeline_years = tco_data.get('timeline_years', 5) self.initial_costs = tco_data.get('initial_costs', {}) self.operational_costs = tco_data.get('operational_costs', {}) self.scaling_params = tco_data.get('scaling_params', {}) self.productivity_factors = tco_data.get('productivity_factors', {}) def calculate_initial_costs(self) -> Dict[str, float]: """ Calculate one-time initial costs. Returns: Dictionary of initial cost components """ costs = { 'licensing': self.initial_costs.get('licensing', 0.0), 'training': self._calculate_training_costs(), 'migration': self.initial_costs.get('migration', 0.0), 'setup': self.initial_costs.get('setup', 0.0), 'tooling': self.initial_costs.get('tooling', 0.0) } costs['total_initial'] = sum(costs.values()) return costs def _calculate_training_costs(self) -> float: """ Calculate training costs based on team size and learning curve. Returns: Total training cost """ # Default training assumptions hours_per_developer = self.initial_costs.get('training_hours_per_dev', 40) avg_hourly_rate = self.initial_costs.get('developer_hourly_rate', 100) training_materials = self.initial_costs.get('training_materials', 500) total_hours = self.team_size * hours_per_developer total_cost = (total_hours * avg_hourly_rate) + training_materials return total_cost def calculate_operational_costs(self) -> Dict[str, List[float]]: """ Calculate ongoing operational costs per year. Returns: Dictionary with yearly cost projections """ yearly_costs = { 'licensing': [], 'hosting': [], 'support': [], 'maintenance': [], 'total_yearly': [] } for year in range(1, self.timeline_years + 1): # Licensing costs (may include annual fees) license_cost = self.operational_costs.get('annual_licensing', 0.0) yearly_costs['licensing'].append(license_cost) # Hosting costs (scale with growth) hosting_cost = self._calculate_hosting_cost(year) yearly_costs['hosting'].append(hosting_cost) # Support costs support_cost = self.operational_costs.get('annual_support', 0.0) yearly_costs['support'].append(support_cost) # Maintenance costs (developer time) maintenance_cost = self._calculate_maintenance_cost(year) yearly_costs['maintenance'].append(maintenance_cost) # Total for year year_total = ( license_cost + hosting_cost + support_cost + maintenance_cost ) yearly_costs['total_yearly'].append(year_total) return yearly_costs def _calculate_hosting_cost(self, year: int) -> float: """ Calculate hosting costs with growth projection. Args: year: Year number (1-indexed) Returns: Hosting cost for the year """ base_cost = self.operational_costs.get('monthly_hosting', 1000.0) * 12 growth_rate = self.scaling_params.get('annual_growth_rate', 0.20) # 20% default # Apply compound growth year_cost = base_cost * ((1 + growth_rate) ** (year - 1)) return year_cost def _calculate_maintenance_cost(self, year: int) -> float: """ Calculate maintenance costs (developer time). Args: year: Year number (1-indexed) Returns: Maintenance cost for the year """ hours_per_dev_per_month = self.operational_costs.get('maintenance_hours_per_dev_monthly', 20) avg_hourly_rate = self.initial_costs.get('developer_hourly_rate', 100) monthly_cost = self.team_size * hours_per_dev_per_month * avg_hourly_rate yearly_cost = monthly_cost * 12 return yearly_cost def calculate_scaling_costs(self) -> Dict[str, Any]: """ Calculate scaling-related costs and metrics. Returns: Dictionary with scaling cost analysis """ # Project user growth initial_users = self.scaling_params.get('initial_users', 1000) annual_growth_rate = self.scaling_params.get('annual_growth_rate', 0.20) user_projections = [] for year in range(1, self.timeline_years + 1): users = initial_users * ((1 + annual_growth_rate) ** year) user_projections.append(int(users)) # Calculate cost per user operational = self.calculate_operational_costs() cost_per_user = [] for year_idx, year_cost in enumerate(operational['total_yearly']): users = user_projections[year_idx] cost_per_user.append(year_cost / users if users > 0 else 0) # Infrastructure scaling costs infra_scaling = self._calculate_infrastructure_scaling() return { 'user_projections': user_projections, 'cost_per_user': cost_per_user, 'infrastructure_scaling': infra_scaling, 'scaling_efficiency': self._calculate_scaling_efficiency(cost_per_user) } def _calculate_infrastructure_scaling(self) -> Dict[str, List[float]]: """ Calculate infrastructure scaling costs. Returns: Infrastructure cost projections """ base_servers = self.scaling_params.get('initial_servers', 5) cost_per_server_monthly = self.scaling_params.get('cost_per_server_monthly', 200) growth_rate = self.scaling_params.get('annual_growth_rate', 0.20) server_costs = [] for year in range(1, self.timeline_years + 1): servers_needed = base_servers * ((1 + growth_rate) ** year) yearly_cost = servers_needed * cost_per_server_monthly * 12 server_costs.append(yearly_cost) return { 'yearly_infrastructure_costs': server_costs } def _calculate_scaling_efficiency(self, cost_per_user: List[float]) -> str: """ Assess scaling efficiency based on cost per user trend. Args: cost_per_user: List of yearly cost per user Returns: Efficiency assessment """ if len(cost_per_user) < 2: return "Insufficient data" # Compare first year to last year initial = cost_per_user[0] final = cost_per_user[-1] if final < initial * 0.8: return "Excellent - economies of scale achieved" elif final < initial: return "Good - improving efficiency over time" elif final < initial * 1.2: return "Moderate - costs growing with users" else: return "Poor - costs growing faster than users" def calculate_productivity_impact(self) -> Dict[str, Any]: """ Calculate developer productivity impact. Returns: Productivity analysis """ # Productivity multiplier (1.0 = baseline) productivity_multiplier = self.productivity_factors.get('productivity_multiplier', 1.0) # Time to market impact (in days) ttm_reduction = self.productivity_factors.get('time_to_market_reduction_days', 0) # Calculate value of faster development avg_feature_time_days = self.productivity_factors.get('avg_feature_time_days', 30) features_per_year = 365 / avg_feature_time_days faster_features_per_year = 365 / max(1, avg_feature_time_days - ttm_reduction) additional_features = faster_features_per_year - features_per_year feature_value = self.productivity_factors.get('avg_feature_value', 10000) yearly_productivity_value = additional_features * feature_value return { 'productivity_multiplier': productivity_multiplier, 'time_to_market_reduction_days': ttm_reduction, 'additional_features_per_year': additional_features, 'yearly_productivity_value': yearly_productivity_value, 'five_year_productivity_value': yearly_productivity_value * self.timeline_years } def calculate_hidden_costs(self) -> Dict[str, float]: """ Identify and calculate hidden costs. Returns: Dictionary of hidden cost components """ costs = { 'technical_debt': self._estimate_technical_debt(), 'vendor_lock_in_risk': self._estimate_vendor_lock_in_cost(), 'security_incidents': self._estimate_security_costs(), 'downtime_risk': self._estimate_downtime_costs(), 'developer_turnover': self._estimate_turnover_costs() } costs['total_hidden_costs'] = sum(costs.values()) return costs def _estimate_technical_debt(self) -> float: """ Estimate technical debt accumulation costs. Returns: Estimated technical debt cost """ # Percentage of development time spent on debt debt_percentage = self.productivity_factors.get('technical_debt_percentage', 0.15) yearly_dev_cost = self._calculate_maintenance_cost(1) # Year 1 baseline # Technical debt accumulates over time total_debt_cost = 0 for year in range(1, self.timeline_years + 1): year_debt = yearly_dev_cost * debt_percentage * year # Increases each year total_debt_cost += year_debt return total_debt_cost def _estimate_vendor_lock_in_cost(self) -> float: """ Estimate cost of vendor lock-in. Returns: Estimated lock-in cost """ lock_in_risk = self.productivity_factors.get('vendor_lock_in_risk', 'low') # Migration cost if switching vendors migration_cost = self.initial_costs.get('migration', 10000) risk_multipliers = { 'low': 0.1, 'medium': 0.3, 'high': 0.6 } multiplier = risk_multipliers.get(lock_in_risk, 0.2) return migration_cost * multiplier def _estimate_security_costs(self) -> float: """ Estimate potential security incident costs. Returns: Estimated security cost """ incidents_per_year = self.productivity_factors.get('security_incidents_per_year', 0.5) avg_incident_cost = self.productivity_factors.get('avg_security_incident_cost', 50000) total_cost = incidents_per_year * avg_incident_cost * self.timeline_years return total_cost def _estimate_downtime_costs(self) -> float: """ Estimate downtime costs. Returns: Estimated downtime cost """ hours_downtime_per_year = self.productivity_factors.get('downtime_hours_per_year', 2) cost_per_hour = self.productivity_factors.get('downtime_cost_per_hour', 5000) total_cost = hours_downtime_per_year * cost_per_hour * self.timeline_years return total_cost def _estimate_turnover_costs(self) -> float: """ Estimate costs from developer turnover. Returns: Estimated turnover cost """ turnover_rate = self.productivity_factors.get('annual_turnover_rate', 0.15) cost_per_hire = self.productivity_factors.get('cost_per_new_hire', 30000) hires_per_year = self.team_size * turnover_rate total_cost = hires_per_year * cost_per_hire * self.timeline_years return total_cost def calculate_total_tco(self) -> Dict[str, Any]: """ Calculate complete TCO over the timeline. Returns: Comprehensive TCO analysis """ initial = self.calculate_initial_costs() operational = self.calculate_operational_costs() scaling = self.calculate_scaling_costs() productivity = self.calculate_productivity_impact() hidden = self.calculate_hidden_costs() # Calculate total costs total_operational = sum(operational['total_yearly']) total_cost = initial['total_initial'] + total_operational + hidden['total_hidden_costs'] # Adjust for productivity gains net_cost = total_cost - productivity['five_year_productivity_value'] return { 'technology': self.technology, 'timeline_years': self.timeline_years, 'initial_costs': initial, 'operational_costs': operational, 'scaling_analysis': scaling, 'productivity_impact': productivity, 'hidden_costs': hidden, 'total_tco': total_cost, 'net_tco_after_productivity': net_cost, 'average_yearly_cost': total_cost / self.timeline_years } def generate_tco_summary(self) -> Dict[str, Any]: """ Generate executive summary of TCO. Returns: TCO summary for reporting """ tco = self.calculate_total_tco() return { 'technology': self.technology, 'total_tco': f"${tco['total_tco']:,.2f}", 'net_tco': f"${tco['net_tco_after_productivity']:,.2f}", 'average_yearly': f"${tco['average_yearly_cost']:,.2f}", 'initial_investment': f"${tco['initial_costs']['total_initial']:,.2f}", 'key_cost_drivers': self._identify_cost_drivers(tco), 'cost_optimization_opportunities': self._identify_optimizations(tco) } def _identify_cost_drivers(self, tco: Dict[str, Any]) -> List[str]: """ Identify top cost drivers. Args: tco: Complete TCO analysis Returns: List of top cost drivers """ drivers = [] # Check operational costs operational = tco['operational_costs'] total_hosting = sum(operational['hosting']) total_maintenance = sum(operational['maintenance']) if total_hosting > total_maintenance: drivers.append(f"Infrastructure/hosting ({total_hosting:,.0f})") else: drivers.append(f"Developer maintenance time ({total_maintenance:,.0f})") # Check hidden costs hidden = tco['hidden_costs'] if hidden['technical_debt'] > 10000: drivers.append(f"Technical debt ({hidden['technical_debt']:,.0f})") return drivers[:3] # Top 3 def _identify_optimizations(self, tco: Dict[str, Any]) -> List[str]: """ Identify cost optimization opportunities. Args: tco: Complete TCO analysis Returns: List of optimization suggestions """ optimizations = [] # Check scaling efficiency scaling = tco['scaling_analysis'] if scaling['scaling_efficiency'].startswith('Poor'): optimizations.append("Improve scaling efficiency - costs growing too fast") # Check hidden costs hidden = tco['hidden_costs'] if hidden['technical_debt'] > 20000: optimizations.append("Address technical debt accumulation") if hidden['downtime_risk'] > 10000: optimizations.append("Invest in reliability to reduce downtime costs") return optimizations