| """
|
| Compatibility Analysis Engine for CanRun
|
| Compatibility analysis for RTX/GTX gaming systems with G-Assist integration.
|
| """
|
|
|
| import re
|
| import logging
|
| from typing import Dict, List, Optional, Tuple, Any
|
| from dataclasses import dataclass
|
| from enum import Enum
|
|
|
| from src.privacy_aware_hardware_detector import PrivacyAwareHardwareSpecs
|
| from src.game_requirements_fetcher import GameRequirements
|
|
|
|
|
| class CompatibilityLevel(Enum):
|
| """Compatibility levels for RTX/GTX gaming systems."""
|
| EXCELLENT = "Excellent"
|
| GOOD = "Good"
|
| ADEQUATE = "Adequate"
|
| POOR = "Poor"
|
| INCOMPATIBLE = "Incompatible"
|
|
|
|
|
| class ComponentType(Enum):
|
| """Hardware component types for RTX/GTX gaming analysis."""
|
| GPU = "GPU"
|
| CPU = "CPU"
|
| RAM = "RAM"
|
| STORAGE = "Storage"
|
| OS = "OS"
|
| DIRECTX = "DirectX"
|
|
|
|
|
| @dataclass
|
| class ComponentAnalysis:
|
| """Analysis result for a single hardware component."""
|
| component: ComponentType
|
| meets_minimum: bool
|
| meets_recommended: bool
|
| score: float
|
| bottleneck_factor: float
|
| details: str
|
| upgrade_suggestion: Optional[str] = None
|
|
|
| def __post_init__(self):
|
| """Validate component analysis after initialization."""
|
| assert 0.0 <= self.score <= 1.0, "Score must be between 0 and 1"
|
| assert 0.0 <= self.bottleneck_factor <= 1.0, "Bottleneck factor must be between 0 and 1"
|
| assert self.details.strip(), "Details cannot be empty"
|
|
|
|
|
| @dataclass
|
| class CompatibilityAnalysis:
|
| """Complete RTX/GTX gaming compatibility analysis result."""
|
| game_name: str
|
| overall_compatibility: CompatibilityLevel
|
| can_run_minimum: bool
|
| can_run_recommended: bool
|
| component_analyses: List[ComponentAnalysis]
|
| bottlenecks: List[ComponentType]
|
| overall_score: float
|
| summary: str
|
| recommendations: List[str]
|
|
|
| def __post_init__(self):
|
| """Validate compatibility analysis after initialization."""
|
| assert self.game_name.strip(), "Game name cannot be empty"
|
| assert 0.0 <= self.overall_score <= 1.0, "Overall score must be between 0 and 1"
|
| assert self.component_analyses, "Component analyses cannot be empty"
|
| assert self.summary.strip(), "Summary cannot be empty"
|
|
|
| def get_minimum_requirements_status(self) -> Dict[str, Any]:
|
| """Get clear status about minimum requirements compliance."""
|
| failing_components = []
|
| meeting_components = []
|
|
|
| for analysis in self.component_analyses:
|
| if analysis.meets_minimum:
|
| meeting_components.append({
|
| 'component': analysis.component.value,
|
| 'status': 'MEETS_MINIMUM',
|
| 'details': analysis.details
|
| })
|
| else:
|
| failing_components.append({
|
| 'component': analysis.component.value,
|
| 'status': 'BELOW_MINIMUM',
|
| 'details': analysis.details,
|
| 'upgrade_suggestion': analysis.upgrade_suggestion
|
| })
|
|
|
| return {
|
| 'can_run_game': self.can_run_minimum,
|
| 'overall_status': 'MEETS_MINIMUM_REQUIREMENTS' if self.can_run_minimum else 'BELOW_MINIMUM_REQUIREMENTS',
|
| 'meeting_components': meeting_components,
|
| 'failing_components': failing_components,
|
| 'summary_message': self._get_minimum_requirements_message()
|
| }
|
|
|
| def _get_minimum_requirements_message(self) -> str:
|
| """Generate clear message about minimum requirements status."""
|
| if self.can_run_minimum:
|
| if self.can_run_recommended:
|
| return f"CANRUN: {self.game_name} will run EXCELLENTLY - System exceeds recommended requirements!"
|
| else:
|
| return f"CANRUN: {self.game_name} will run - System meets minimum requirements!"
|
| else:
|
| failing_components = [c.component.value for c in self.component_analyses if not c.meets_minimum]
|
| return f" CANNOT RUN: {self.game_name} requires upgrades - Failing components: {', '.join(failing_components)}"
|
|
|
| def get_runnable_status(self) -> str:
|
| """Get simple runnable status message."""
|
| return self._get_minimum_requirements_message()
|
|
|
|
|
| class CompatibilityAnalyzer:
|
| """Compatibility analyzer for RTX/GTX gaming systems."""
|
|
|
| def __init__(self, llm_analyzer=None):
|
| self.logger = logging.getLogger(__name__)
|
| self.llm_analyzer = llm_analyzer
|
|
|
|
|
| self.component_weights = {
|
| ComponentType.GPU: 0.45,
|
| ComponentType.CPU: 0.30,
|
| ComponentType.RAM: 0.15,
|
| ComponentType.STORAGE: 0.05,
|
| ComponentType.OS: 0.03,
|
| ComponentType.DIRECTX: 0.02
|
| }
|
|
|
|
|
| self.nvidia_gpu_tiers = {
|
|
|
| 'rtx 4090': 100, 'rtx 4080': 90, 'rtx 4070 ti': 80, 'rtx 4070': 75,
|
| 'rtx 4060 ti': 65, 'rtx 4060': 60,
|
|
|
| 'rtx 3090': 95, 'rtx 3080': 85, 'rtx 3070': 70, 'rtx 3060 ti': 60,
|
| 'rtx 3060': 55, 'rtx 3050': 45,
|
|
|
| 'rtx 2080 ti': 80, 'rtx 2080': 70, 'rtx 2070': 60, 'rtx 2060': 50,
|
|
|
| 'gtx 1660 ti': 45, 'gtx 1660': 40, 'gtx 1650': 30,
|
|
|
| 'gtx 1080 ti': 65, 'gtx 1080': 55, 'gtx 1070': 45, 'gtx 1060': 35,
|
| 'gtx 1050': 25
|
| }
|
|
|
| self.logger.info("RTX/GTX compatibility analyzer initialized")
|
|
|
| def analyze_compatibility(self, game_name: str, hardware: PrivacyAwareHardwareSpecs,
|
| requirements: GameRequirements) -> CompatibilityAnalysis:
|
| """Perform complete RTX/GTX gaming compatibility analysis."""
|
|
|
| assert game_name and game_name.strip(), "Game name must be provided"
|
| assert hardware.is_nvidia_gpu, "RTX/GTX GPU required for G-Assist compatibility"
|
| assert requirements.game_name.strip(), "Game requirements must be valid"
|
|
|
|
|
| component_analyses = [
|
| self._analyze_nvidia_gpu(hardware, requirements),
|
| self._analyze_cpu(hardware, requirements),
|
| self._analyze_ram(hardware, requirements),
|
| self._analyze_storage(hardware, requirements),
|
| self._analyze_os(hardware, requirements),
|
| self._analyze_directx(hardware, requirements)
|
| ]
|
|
|
|
|
| overall_score = self._calculate_overall_score(component_analyses)
|
| overall_compatibility = self._determine_compatibility_level(overall_score)
|
|
|
|
|
| can_run_minimum = all(c.meets_minimum for c in component_analyses)
|
| can_run_recommended = all(c.meets_recommended for c in component_analyses)
|
|
|
|
|
| bottlenecks = self._identify_bottlenecks(component_analyses)
|
|
|
|
|
| summary = self._generate_summary(overall_compatibility, can_run_minimum,
|
| can_run_recommended, bottlenecks)
|
| recommendations = self._generate_recommendations(component_analyses, bottlenecks, hardware)
|
|
|
| return CompatibilityAnalysis(
|
| game_name=requirements.game_name,
|
| overall_compatibility=overall_compatibility,
|
| can_run_minimum=can_run_minimum,
|
| can_run_recommended=can_run_recommended,
|
| component_analyses=component_analyses,
|
| bottlenecks=bottlenecks,
|
| overall_score=overall_score,
|
| summary=summary,
|
| recommendations=recommendations
|
| )
|
|
|
| def _analyze_nvidia_gpu(self, hardware: PrivacyAwareHardwareSpecs,
|
| requirements: GameRequirements) -> ComponentAnalysis:
|
| """Analyze RTX/GTX GPU compatibility."""
|
| assert hardware.is_nvidia_gpu, "RTX/GTX GPU required"
|
|
|
|
|
| gpu_score = self._get_nvidia_gpu_score(hardware.gpu_model)
|
|
|
|
|
| min_gpu_text = requirements.minimum_gpu.lower()
|
| rec_gpu_text = requirements.recommended_gpu.lower()
|
|
|
| min_score = self._estimate_required_gpu_score(min_gpu_text)
|
| rec_score = self._estimate_required_gpu_score(rec_gpu_text)
|
|
|
|
|
| meets_minimum = gpu_score >= min_score
|
| meets_recommended = gpu_score >= rec_score
|
|
|
|
|
| score = min(1.0, gpu_score / max(rec_score, 1))
|
| bottleneck_factor = max(0.0, (min_score - gpu_score) / max(min_score, 1))
|
|
|
|
|
| rtx_features = []
|
| if hardware.supports_rtx:
|
| rtx_features.append("RTX Ray Tracing")
|
| if hardware.supports_dlss:
|
| rtx_features.append("DLSS")
|
|
|
| details = f"NVIDIA {hardware.gpu_model} ({hardware.gpu_vram_gb}GB VRAM"
|
| if rtx_features:
|
| details += f", {', '.join(rtx_features)}"
|
| details += ")"
|
|
|
| if meets_recommended:
|
| details += " - Exceeds recommended requirements"
|
| elif meets_minimum:
|
| details += " - Meets minimum requirements"
|
| else:
|
| details += " - Below minimum requirements"
|
|
|
|
|
| upgrade_suggestion = None
|
| if not meets_minimum:
|
| upgrade_suggestion = "Consider upgrading to a more powerful RTX GPU"
|
| elif not meets_recommended:
|
| upgrade_suggestion = "RTX upgrade recommended for better performance and ray tracing"
|
|
|
| return ComponentAnalysis(
|
| component=ComponentType.GPU,
|
| meets_minimum=meets_minimum,
|
| meets_recommended=meets_recommended,
|
| score=score,
|
| bottleneck_factor=bottleneck_factor,
|
| details=details,
|
| upgrade_suggestion=upgrade_suggestion
|
| )
|
|
|
| def _analyze_cpu(self, hardware: PrivacyAwareHardwareSpecs,
|
| requirements: GameRequirements) -> ComponentAnalysis:
|
| """Analyze CPU compatibility for RTX/GTX gaming."""
|
| assert hardware.cpu_cores > 0, "CPU cores must be greater than 0"
|
| assert hardware.cpu_threads > 0, "CPU threads must be greater than 0"
|
|
|
|
|
| cpu_score = self._estimate_cpu_performance(hardware.cpu_model, hardware.cpu_cores, hardware.cpu_threads)
|
|
|
|
|
| min_cpu_text = requirements.minimum_cpu.lower()
|
| rec_cpu_text = requirements.recommended_cpu.lower()
|
|
|
| min_score = self._estimate_required_cpu_score(min_cpu_text)
|
| rec_score = self._estimate_required_cpu_score(rec_cpu_text)
|
|
|
|
|
| meets_minimum = cpu_score >= min_score
|
| meets_recommended = cpu_score >= rec_score
|
|
|
|
|
| score = min(1.0, cpu_score / max(rec_score, 1))
|
| bottleneck_factor = max(0.0, (min_score - cpu_score) / max(min_score, 1))
|
|
|
|
|
| details = f"CPU: {hardware.cpu_model} ({hardware.cpu_cores}C/{hardware.cpu_threads}T)"
|
|
|
| if meets_recommended:
|
| details += " - Exceeds recommended requirements"
|
| elif meets_minimum:
|
| details += " - Meets minimum requirements"
|
| else:
|
| details += " - Below minimum requirements"
|
|
|
|
|
| upgrade_suggestion = None
|
| if not meets_minimum:
|
| upgrade_suggestion = "Consider upgrading to a faster CPU"
|
| elif not meets_recommended:
|
| upgrade_suggestion = "CPU upgrade recommended for optimal NVIDIA gaming performance"
|
|
|
| return ComponentAnalysis(
|
| component=ComponentType.CPU,
|
| meets_minimum=meets_minimum,
|
| meets_recommended=meets_recommended,
|
| score=score,
|
| bottleneck_factor=bottleneck_factor,
|
| details=details,
|
| upgrade_suggestion=upgrade_suggestion
|
| )
|
|
|
| def _analyze_ram(self, hardware: PrivacyAwareHardwareSpecs,
|
| requirements: GameRequirements) -> ComponentAnalysis:
|
| """Analyze RAM compatibility."""
|
| assert hardware.ram_total_gb > 0, "RAM must be greater than 0"
|
|
|
|
|
| min_ram = requirements.minimum_ram_gb
|
| rec_ram = requirements.recommended_ram_gb
|
|
|
|
|
|
|
| min_ram_with_tolerance = min_ram * 0.95
|
| rec_ram_with_tolerance = rec_ram * 0.95
|
|
|
|
|
| self.logger.info(f"RAM comparison: System has {hardware.ram_total_gb}GB, min required: {min_ram}GB "
|
| f"(with tolerance: {min_ram_with_tolerance:.1f}GB), "
|
| f"recommended: {rec_ram}GB (with tolerance: {rec_ram_with_tolerance:.1f}GB)")
|
|
|
|
|
| meets_minimum = hardware.ram_total_gb >= min_ram_with_tolerance
|
| meets_recommended = hardware.ram_total_gb >= rec_ram_with_tolerance
|
|
|
|
|
| score = min(1.0, hardware.ram_total_gb / max(rec_ram, 1))
|
| bottleneck_factor = max(0.0, (min_ram - hardware.ram_total_gb) / max(min_ram, 1))
|
|
|
|
|
| details = f"RAM: {hardware.ram_total_gb}GB"
|
|
|
| if meets_recommended:
|
| details += " - Sufficient for recommended settings"
|
| elif meets_minimum:
|
| details += " - Meets minimum requirements"
|
| else:
|
| details += " - Insufficient RAM"
|
|
|
|
|
| upgrade_suggestion = None
|
| if not meets_minimum:
|
| upgrade_suggestion = f"Add more RAM (need at least {min_ram}GB)"
|
| elif not meets_recommended:
|
| upgrade_suggestion = f"Consider upgrading to {rec_ram}GB for better performance"
|
|
|
| return ComponentAnalysis(
|
| component=ComponentType.RAM,
|
| meets_minimum=meets_minimum,
|
| meets_recommended=meets_recommended,
|
| score=score,
|
| bottleneck_factor=bottleneck_factor,
|
| details=details,
|
| upgrade_suggestion=upgrade_suggestion
|
| )
|
|
|
| def _analyze_storage(self, hardware: PrivacyAwareHardwareSpecs,
|
| requirements: GameRequirements) -> ComponentAnalysis:
|
| """Analyze storage compatibility."""
|
|
|
| min_storage = requirements.minimum_storage_gb
|
| rec_storage = requirements.recommended_storage_gb
|
|
|
|
|
|
|
| meets_minimum = True
|
| meets_recommended = True
|
| score = 1.0
|
| bottleneck_factor = 0.0
|
|
|
| details = f"Storage: {min_storage}GB required"
|
| if rec_storage > min_storage:
|
| details += f" ({rec_storage}GB recommended)"
|
|
|
| return ComponentAnalysis(
|
| component=ComponentType.STORAGE,
|
| meets_minimum=meets_minimum,
|
| meets_recommended=meets_recommended,
|
| score=score,
|
| bottleneck_factor=bottleneck_factor,
|
| details=details
|
| )
|
|
|
| def _analyze_os(self, hardware: PrivacyAwareHardwareSpecs,
|
| requirements: GameRequirements) -> ComponentAnalysis:
|
| """Analyze OS compatibility for NVIDIA gaming."""
|
| assert hardware.os_version.strip(), "OS version cannot be empty"
|
|
|
|
|
| min_os = requirements.minimum_os.lower()
|
| rec_os = requirements.recommended_os.lower()
|
|
|
| is_windows = 'windows' in hardware.os_version.lower()
|
| meets_minimum = is_windows and ('windows' in min_os or not min_os)
|
| meets_recommended = is_windows and ('windows' in rec_os or not rec_os)
|
|
|
| score = 1.0 if meets_minimum else 0.0
|
| bottleneck_factor = 0.0 if meets_minimum else 1.0
|
|
|
| details = f"OS: {hardware.os_version}"
|
| if meets_minimum:
|
| details += " - Compatible with G-Assist"
|
| else:
|
| details += " - May not be compatible with G-Assist"
|
|
|
| upgrade_suggestion = None
|
| if not meets_minimum:
|
| upgrade_suggestion = "Windows OS recommended for full G-Assist compatibility"
|
|
|
| return ComponentAnalysis(
|
| component=ComponentType.OS,
|
| meets_minimum=meets_minimum,
|
| meets_recommended=meets_recommended,
|
| score=score,
|
| bottleneck_factor=bottleneck_factor,
|
| details=details,
|
| upgrade_suggestion=upgrade_suggestion
|
| )
|
|
|
| def _analyze_directx(self, hardware: PrivacyAwareHardwareSpecs,
|
| requirements: GameRequirements) -> ComponentAnalysis:
|
| """Analyze DirectX compatibility."""
|
| assert hardware.directx_version.strip(), "DirectX version cannot be empty"
|
|
|
|
|
| hardware_dx_version = self._extract_directx_version(hardware.directx_version)
|
| min_dx_version = self._extract_directx_version(requirements.minimum_directx)
|
| rec_dx_version = self._extract_directx_version(requirements.recommended_directx)
|
|
|
| meets_minimum = hardware_dx_version >= min_dx_version
|
| meets_recommended = hardware_dx_version >= rec_dx_version
|
|
|
| score = 1.0 if meets_minimum else 0.0
|
| bottleneck_factor = 0.0 if meets_minimum else 0.5
|
|
|
| details = f"DirectX: {hardware.directx_version}"
|
| if meets_recommended:
|
| details += " - Fully supported"
|
| elif meets_minimum:
|
| details += " - Minimum version supported"
|
| else:
|
| details += " - Version may be insufficient"
|
|
|
| upgrade_suggestion = None
|
| if not meets_minimum:
|
| upgrade_suggestion = "Update DirectX to the latest version"
|
|
|
| return ComponentAnalysis(
|
| component=ComponentType.DIRECTX,
|
| meets_minimum=meets_minimum,
|
| meets_recommended=meets_recommended,
|
| score=score,
|
| bottleneck_factor=bottleneck_factor,
|
| details=details,
|
| upgrade_suggestion=upgrade_suggestion
|
| )
|
|
|
| def _get_nvidia_gpu_score(self, gpu_name: str) -> int:
|
| """Get NVIDIA GPU performance score."""
|
| assert gpu_name.strip(), "GPU name cannot be empty"
|
|
|
| gpu_lower = gpu_name.lower()
|
|
|
|
|
| for gpu_key, score in self.nvidia_gpu_tiers.items():
|
| if gpu_key in gpu_lower:
|
| return score
|
|
|
|
|
| if 'rtx 40' in gpu_lower:
|
| return 70
|
| elif 'rtx 30' in gpu_lower:
|
| return 60
|
| elif 'rtx 20' in gpu_lower:
|
| return 50
|
| elif 'gtx 16' in gpu_lower:
|
| return 40
|
| elif 'gtx 10' in gpu_lower:
|
| return 35
|
| else:
|
| return 30
|
|
|
| def _estimate_cpu_performance(self, cpu_model: str, cores: int, threads: int) -> int:
|
| """Estimate CPU performance score."""
|
| assert cpu_model.strip(), "CPU model cannot be empty"
|
| assert cores > 0, "CPU cores must be greater than 0"
|
| assert threads > 0, "CPU threads must be greater than 0"
|
|
|
| cpu_lower = cpu_model.lower()
|
| base_score = 50
|
|
|
|
|
| if 'intel' in cpu_lower:
|
| if 'i9' in cpu_lower:
|
| base_score = 90
|
| elif 'i7' in cpu_lower:
|
| base_score = 80
|
| elif 'i5' in cpu_lower:
|
| base_score = 70
|
| elif 'i3' in cpu_lower:
|
| base_score = 60
|
|
|
|
|
| elif 'amd' in cpu_lower:
|
| if 'ryzen 9' in cpu_lower:
|
| base_score = 90
|
| elif 'ryzen 7' in cpu_lower:
|
| base_score = 80
|
| elif 'ryzen 5' in cpu_lower:
|
| base_score = 70
|
| elif 'ryzen 3' in cpu_lower:
|
| base_score = 60
|
|
|
|
|
| core_multiplier = min(1.5, cores / 4)
|
| thread_multiplier = min(1.2, threads / cores)
|
|
|
| return int(base_score * core_multiplier * thread_multiplier)
|
|
|
| def _calculate_overall_score(self, component_analyses: List[ComponentAnalysis]) -> float:
|
| """Calculate weighted overall performance score."""
|
| assert component_analyses, "Component analyses cannot be empty"
|
|
|
| total_score = 0.0
|
| total_weight = 0.0
|
|
|
| for analysis in component_analyses:
|
| weight = self.component_weights.get(analysis.component, 0.1)
|
| total_score += analysis.score * weight
|
| total_weight += weight
|
|
|
| return total_score / total_weight if total_weight > 0 else 0.0
|
|
|
| def _determine_compatibility_level(self, score: float) -> CompatibilityLevel:
|
| """Determine compatibility level based on score."""
|
| assert 0.0 <= score <= 1.0, "Score must be between 0 and 1"
|
|
|
| if score >= 0.9:
|
| return CompatibilityLevel.EXCELLENT
|
| elif score >= 0.7:
|
| return CompatibilityLevel.GOOD
|
| elif score >= 0.5:
|
| return CompatibilityLevel.ADEQUATE
|
| elif score >= 0.3:
|
| return CompatibilityLevel.POOR
|
| else:
|
| return CompatibilityLevel.INCOMPATIBLE
|
|
|
| def _identify_bottlenecks(self, component_analyses: List[ComponentAnalysis]) -> List[ComponentType]:
|
| """Identify component bottlenecks."""
|
| assert component_analyses, "Component analyses cannot be empty"
|
|
|
| bottlenecks = []
|
| for analysis in component_analyses:
|
| if analysis.bottleneck_factor > 0.3:
|
| bottlenecks.append(analysis.component)
|
|
|
| return bottlenecks
|
|
|
| def _generate_summary(self, compatibility: CompatibilityLevel, can_run_min: bool,
|
| can_run_rec: bool, bottlenecks: List[ComponentType]) -> str:
|
| """Generate NVIDIA gaming compatibility summary."""
|
| if compatibility == CompatibilityLevel.EXCELLENT:
|
| return "Your NVIDIA RTX/GTX system exceeds recommended requirements and will run this game excellently with full G-Assist support."
|
| elif compatibility == CompatibilityLevel.GOOD:
|
| return "Your NVIDIA RTX/GTX system meets recommended requirements and will run this game well with G-Assist features."
|
| elif compatibility == CompatibilityLevel.ADEQUATE:
|
| return "Your NVIDIA RTX/GTX system meets minimum requirements but may need setting adjustments for optimal performance."
|
| elif compatibility == CompatibilityLevel.POOR:
|
| return "Your NVIDIA RTX/GTX system barely meets requirements and may experience performance issues."
|
| else:
|
| return "Your NVIDIA RTX/GTX system does not meet minimum requirements for this game."
|
|
|
| def _generate_recommendations(self, component_analyses: List[ComponentAnalysis],
|
| bottlenecks: List[ComponentType],
|
| hardware: PrivacyAwareHardwareSpecs) -> List[str]:
|
| """Generate NVIDIA gaming recommendations."""
|
| recommendations = []
|
|
|
|
|
| for analysis in component_analyses:
|
| if analysis.upgrade_suggestion:
|
| recommendations.append(analysis.upgrade_suggestion)
|
|
|
|
|
| if ComponentType.GPU in bottlenecks:
|
| recommendations.append("Consider upgrading to a newer NVIDIA RTX GPU for better ray tracing and DLSS performance")
|
|
|
|
|
| if hardware.supports_rtx and ComponentType.GPU not in bottlenecks:
|
| recommendations.append("Enable ray tracing if supported by the game for enhanced visual quality")
|
|
|
| if hardware.supports_dlss and ComponentType.GPU not in bottlenecks:
|
| recommendations.append("Enable DLSS if supported by the game for improved performance")
|
|
|
| return recommendations
|
|
|
|
|
| def _extract_ram_amount(self, ram_text: str) -> int:
|
| """Extract RAM amount in GB from text."""
|
| if not ram_text:
|
| return 8
|
|
|
|
|
| match = re.search(r'(\d+)\s*GB', ram_text.upper())
|
| if match:
|
| return int(match.group(1))
|
|
|
|
|
| match = re.search(r'(\d+)\s*MB', ram_text.upper())
|
| if match:
|
| return max(1, int(match.group(1)) // 1024)
|
|
|
| return 8
|
|
|
| def _extract_storage_amount(self, storage_text: str) -> int:
|
| """Extract storage amount in GB from text."""
|
| if not storage_text:
|
| return 50
|
|
|
|
|
| match = re.search(r'(\d+)\s*GB', storage_text.upper())
|
| if match:
|
| return int(match.group(1))
|
|
|
| return 50
|
|
|
| def _extract_directx_version(self, dx_text: str) -> float:
|
| """Extract DirectX version number."""
|
| if not dx_text:
|
| return 12.0
|
|
|
|
|
| match = re.search(r'(\d+)\.?(\d*)', dx_text.upper())
|
| if match:
|
| major = int(match.group(1))
|
| minor = int(match.group(2)) if match.group(2) else 0
|
| return major + (minor / 10)
|
|
|
| return 12.0
|
|
|
| def _estimate_required_gpu_score(self, gpu_text: str) -> int:
|
| """Estimate required GPU score from game requirements text."""
|
| if not gpu_text:
|
| return 30
|
|
|
| gpu_lower = gpu_text.lower()
|
|
|
|
|
| for gpu_key, score in self.nvidia_gpu_tiers.items():
|
| if gpu_key in gpu_lower:
|
| return score
|
|
|
|
|
| if 'rtx' in gpu_lower:
|
| return 50
|
| elif 'gtx' in gpu_lower:
|
| return 40
|
| elif 'nvidia' in gpu_lower:
|
| return 35
|
|
|
| return 30
|
|
|
| def _estimate_required_cpu_score(self, cpu_text: str) -> int:
|
| """Estimate required CPU score from game requirements text."""
|
| if not cpu_text:
|
| return 50
|
|
|
| cpu_lower = cpu_text.lower()
|
|
|
|
|
| if 'i9' in cpu_lower:
|
| return 80
|
| elif 'i7' in cpu_lower:
|
| return 70
|
| elif 'i5' in cpu_lower:
|
| return 60
|
| elif 'i3' in cpu_lower:
|
| return 50
|
|
|
|
|
| elif 'ryzen 9' in cpu_lower:
|
| return 80
|
| elif 'ryzen 7' in cpu_lower:
|
| return 70
|
| elif 'ryzen 5' in cpu_lower:
|
| return 60
|
| elif 'ryzen 3' in cpu_lower:
|
| return 50
|
|
|
| return 50
|
|
|
| async def get_llm_analysis_context(self, game_name: str, hardware: PrivacyAwareHardwareSpecs,
|
| requirements: GameRequirements, analysis: CompatibilityAnalysis) -> Dict[str, Any]:
|
| """Provide structured context for LLM analysis with all compatibility data."""
|
| try:
|
|
|
| context = {
|
| 'game_name': game_name,
|
| 'hardware_specs': {
|
| 'gpu_model': hardware.gpu_model,
|
| 'gpu_vram_gb': hardware.gpu_vram_gb,
|
| 'cpu_model': hardware.cpu_model,
|
| 'cpu_cores': hardware.cpu_cores,
|
| 'cpu_threads': hardware.cpu_threads,
|
| 'ram_total_gb': hardware.ram_total_gb,
|
| 'os_version': hardware.os_version,
|
| 'directx_version': hardware.directx_version,
|
| 'supports_rtx': hardware.supports_rtx,
|
| 'supports_dlss': hardware.supports_dlss,
|
| 'is_nvidia_gpu': hardware.is_nvidia_gpu
|
| },
|
| 'game_requirements': {
|
| 'minimum': {
|
| 'cpu': requirements.minimum_cpu,
|
| 'gpu': requirements.minimum_gpu,
|
| 'ram_gb': requirements.minimum_ram_gb,
|
| 'vram_gb': requirements.minimum_vram_gb,
|
| 'storage_gb': requirements.minimum_storage_gb,
|
| 'directx': requirements.minimum_directx,
|
| 'os': requirements.minimum_os
|
| },
|
| 'recommended': {
|
| 'cpu': requirements.recommended_cpu,
|
| 'gpu': requirements.recommended_gpu,
|
| 'ram_gb': requirements.recommended_ram_gb,
|
| 'vram_gb': requirements.recommended_vram_gb,
|
| 'storage_gb': requirements.recommended_storage_gb,
|
| 'directx': requirements.recommended_directx,
|
| 'os': requirements.recommended_os
|
| },
|
| 'source': requirements.source
|
| },
|
| 'compatibility_analysis': {
|
| 'overall_compatibility': analysis.overall_compatibility.value,
|
| 'can_run_minimum': analysis.can_run_minimum,
|
| 'can_run_recommended': analysis.can_run_recommended,
|
| 'overall_score': analysis.overall_score,
|
| 'summary': analysis.summary,
|
| 'recommendations': analysis.recommendations,
|
| 'bottlenecks': [b.value for b in analysis.bottlenecks],
|
| 'component_analyses': [
|
| {
|
| 'component': comp.component.value,
|
| 'meets_minimum': comp.meets_minimum,
|
| 'meets_recommended': comp.meets_recommended,
|
| 'score': comp.score,
|
| 'bottleneck_factor': comp.bottleneck_factor,
|
| 'details': comp.details,
|
| 'upgrade_suggestion': comp.upgrade_suggestion
|
| }
|
| for comp in analysis.component_analyses
|
| ]
|
| }
|
| }
|
|
|
|
|
| if self.llm_analyzer:
|
| try:
|
| llm_result = await self.llm_analyzer.analyze(
|
| context,
|
| self.llm_analyzer.LLMAnalysisType.DEEP_SYSTEM_ANALYSIS
|
| )
|
|
|
|
|
| context['llm_analysis'] = {
|
| 'confidence_score': llm_result.confidence_score,
|
| 'analysis_text': llm_result.analysis_text,
|
| 'structured_data': llm_result.structured_data,
|
| 'recommendations': llm_result.recommendations,
|
| 'processing_time_ms': llm_result.processing_time_ms,
|
| 'g_assist_used': llm_result.g_assist_used
|
| }
|
|
|
| self.logger.info(f"LLM enhanced compatibility analysis for {game_name}")
|
|
|
| except Exception as e:
|
| self.logger.warning(f"LLM analysis failed: {e}")
|
| context['llm_analysis'] = {'error': str(e)}
|
|
|
| return context
|
|
|
| except Exception as e:
|
| self.logger.error(f"Failed to create LLM analysis context: {e}")
|
| return {
|
| 'game_name': game_name,
|
| 'error': str(e),
|
| 'fallback_data': {
|
| 'can_run': analysis.can_run_minimum if analysis else False,
|
| 'summary': analysis.summary if analysis else "Analysis failed"
|
| }
|
| } |