File size: 6,441 Bytes
8b7488c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d86b25e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
"""
CanRun Game Compatibility Checker - Simple MCP Server Implementation
"""

import gradio as gr
import logging
import os
import signal
import sys
import time
import asyncio
import base64
import platform

# Platform detection
IS_WINDOWS = platform.system() == "Windows"
from src.canrun_engine import CanRunEngine
from plugin import CanRunGAssistPlugin

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
    handlers=[logging.StreamHandler(sys.stdout)]
)
logger = logging.getLogger(__name__)

def signal_handler(signum, frame):
    """Handle shutdown signals gracefully."""
    logger.info(f"Received signal {signum}, shutting down gracefully...")
    sys.exit(0)

async def analyze_game(game_name):
    """Analyze game compatibility using the CanRun engine"""
    if not game_name:
        return "Please enter a game name to begin the analysis."
    
    try:
        plugin = CanRunGAssistPlugin()
        params = {"game_name": game_name, "force_refresh": True}
        # Properly await the async method
        response = await plugin.check_game_compatibility(params)
        
        if response.get("success", False):
            return response.get("message", "Analysis completed successfully.")
        else:
            return response.get("message", "Could not analyze the game. Please check the game name and try again.")
    except Exception as e:
        logger.error(f"Error analyzing game: {e}")
        return f"An error occurred during analysis: {e}"

def detect_hardware():
    """Detect hardware specifications"""
    try:
        plugin = CanRunGAssistPlugin()
        response = plugin.detect_hardware({})
        
        if response.get("success", False):
            return response.get("message", "Hardware detection successful.")
        else:
            return response.get("message", "Could not detect hardware specifications.")
    except Exception as e:
        logger.error(f"Error detecting hardware: {e}")
        return f"An error occurred during hardware detection: {e}"

def get_logo_html():
    """Get HTML that displays the logo"""
    logo_path = os.path.join(os.path.dirname(__file__), "logo.png")
    
    if os.path.exists(logo_path):
        # Read the logo file and encode it as base64
        with open(logo_path, "rb") as image_file:
            encoded_image = base64.b64encode(image_file.read()).decode("utf-8")
        
        # Return HTML that displays the logo
        return f"""
        <div style="display: flex; align-items: center; margin-bottom: 0.5em">
            <img src="data:image/png;base64,{encoded_image}" alt="CanRun Logo" style="height: 4em; margin-right: 1em;">
            <div>
                <h1 style="margin: 0; padding: 0">CanRun Game Compatibility Checker</h1>
                <p style="margin: 0; padding: 0">Check if your PC can run any game with an advanced tier system and Steam API integration</p>
            </div>
        </div>
        """
    else:
        logger.warning(f"Logo file not found at {logo_path}")
        return """
        <div>
            <h1>CanRun Game Compatibility Checker</h1>
            <p>Check if your PC can run any game with an advanced tier system and Steam API integration</p>
        </div>
        """

def create_gradio_interface():
    """Create a simple Gradio interface with logo and favicon"""
    # Set custom theme with brand color matching the logo
    theme = gr.themes.Default(
        primary_hue="green",
        secondary_hue="gray",
    )
    
    # Define file paths
    favicon_path = os.path.join(os.path.dirname(__file__), "logo.png")
    
    with gr.Blocks(theme=theme, title="CanRun - Game Compatibility Checker", css="") as demo:
        # Header with logo
        gr.HTML(get_logo_html())
        
        # Main content
        with gr.Row():
            with gr.Column():
                game_input = gr.Textbox(label="Game Name", placeholder="Enter game name (e.g., Diablo 4)")
                check_btn = gr.Button("Check Compatibility", variant="primary")
                hw_btn = gr.Button("Detect Hardware", variant="secondary")
            
            with gr.Column():
                result_output = gr.Textbox(label="Results", lines=20)
        
        # Footer
        gr.HTML("""
        <div style="margin-top: 20px; text-align: center; padding: 10px; border-top: 1px solid #ddd;">
            <p>CanRun - Advanced Game Compatibility Checker with MCP Server Support</p>
            <p>Powered by G-Assist Integration</p>
        </div>
        """)
        
        # For async functions, we need to use .click(fn=..., inputs=..., outputs=...)
        check_btn.click(fn=analyze_game, inputs=game_input, outputs=result_output)
        hw_btn.click(fn=detect_hardware, inputs=None, outputs=result_output)
    
    return demo

def is_mcp_available():
    """Check if the MCP package is available"""
    try:
        import mcp
        return True
    except ImportError:
        return False

def main():
    """Main application entry point"""
    # Set up signal handlers
    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)
    
    logger.info("Starting CanRun Game Compatibility Checker")
    
    # Create Gradio interface
    demo = create_gradio_interface()
    
    # Check if MCP support is available
    mcp_enabled = is_mcp_available()
    if mcp_enabled:
        logger.info("MCP server functionality is enabled")
    else:
        logger.info("MCP server functionality is disabled. Install with 'pip install \"gradio[mcp]\"' to enable")
    
    # Launch with auto port discovery
    launch_kwargs = {
        "server_name": "0.0.0.0", 
        "share": False,
        "favicon_path": os.path.join(os.path.dirname(__file__), "logo.png"),
    }
    
    # Only enable MCP server if the package is available
    if mcp_enabled:
        launch_kwargs["mcp_server"] = True
    
    # Launch the server
    demo.queue().launch(**launch_kwargs)
    
    # Keep the main thread alive - Platform-independent approach
    logger.info("Press Ctrl+C to stop the server")
    try:
        # This works on most systems and is more reliable than signal.pause()
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        logger.info("Keyboard interrupt received, shutting down...")
        sys.exit(0)

if __name__ == "__main__":
    main()