grasant commited on
Commit
8b7488c
·
verified ·
1 Parent(s): d86b25e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +183 -179
app.py CHANGED
@@ -1,180 +1,184 @@
1
- """
2
- CanRun Game Compatibility Checker - Simple MCP Server Implementation
3
- """
4
-
5
- import gradio as gr
6
- import logging
7
- import os
8
- import signal
9
- import sys
10
- import time
11
- import asyncio
12
- import base64
13
- from src.canrun_engine import CanRunEngine
14
- from plugin import CanRunGAssistPlugin
15
-
16
- # Configure logging
17
- logging.basicConfig(
18
- level=logging.INFO,
19
- format="%(asctime)s - %(levelname)s - %(message)s",
20
- handlers=[logging.StreamHandler(sys.stdout)]
21
- )
22
- logger = logging.getLogger(__name__)
23
-
24
- def signal_handler(signum, frame):
25
- """Handle shutdown signals gracefully."""
26
- logger.info(f"Received signal {signum}, shutting down gracefully...")
27
- sys.exit(0)
28
-
29
- async def analyze_game(game_name):
30
- """Analyze game compatibility using the CanRun engine"""
31
- if not game_name:
32
- return "Please enter a game name to begin the analysis."
33
-
34
- try:
35
- plugin = CanRunGAssistPlugin()
36
- params = {"game_name": game_name, "force_refresh": True}
37
- # Properly await the async method
38
- response = await plugin.check_game_compatibility(params)
39
-
40
- if response.get("success", False):
41
- return response.get("message", "Analysis completed successfully.")
42
- else:
43
- return response.get("message", "Could not analyze the game. Please check the game name and try again.")
44
- except Exception as e:
45
- logger.error(f"Error analyzing game: {e}")
46
- return f"An error occurred during analysis: {e}"
47
-
48
- def detect_hardware():
49
- """Detect hardware specifications"""
50
- try:
51
- plugin = CanRunGAssistPlugin()
52
- response = plugin.detect_hardware({})
53
-
54
- if response.get("success", False):
55
- return response.get("message", "Hardware detection successful.")
56
- else:
57
- return response.get("message", "Could not detect hardware specifications.")
58
- except Exception as e:
59
- logger.error(f"Error detecting hardware: {e}")
60
- return f"An error occurred during hardware detection: {e}"
61
-
62
- def get_logo_html():
63
- """Get HTML that displays the logo"""
64
- logo_path = os.path.join(os.path.dirname(__file__), "logo.png")
65
-
66
- if os.path.exists(logo_path):
67
- # Read the logo file and encode it as base64
68
- with open(logo_path, "rb") as image_file:
69
- encoded_image = base64.b64encode(image_file.read()).decode("utf-8")
70
-
71
- # Return HTML that displays the logo
72
- return f"""
73
- <div style="display: flex; align-items: center; margin-bottom: 0.5em">
74
- <img src="data:image/png;base64,{encoded_image}" alt="CanRun Logo" style="height: 4em; margin-right: 1em;">
75
- <div>
76
- <h1 style="margin: 0; padding: 0">CanRun Game Compatibility Checker</h1>
77
- <p style="margin: 0; padding: 0">Check if your PC can run any game with an advanced tier system and Steam API integration</p>
78
- </div>
79
- </div>
80
- """
81
- else:
82
- logger.warning(f"Logo file not found at {logo_path}")
83
- return """
84
- <div>
85
- <h1>CanRun Game Compatibility Checker</h1>
86
- <p>Check if your PC can run any game with an advanced tier system and Steam API integration</p>
87
- </div>
88
- """
89
-
90
- def create_gradio_interface():
91
- """Create a simple Gradio interface with logo and favicon"""
92
- # Set custom theme with brand color matching the logo
93
- theme = gr.themes.Default(
94
- primary_hue="green",
95
- secondary_hue="gray",
96
- )
97
-
98
- # Define file paths
99
- favicon_path = os.path.join(os.path.dirname(__file__), "logo.png")
100
-
101
- with gr.Blocks(theme=theme, title="CanRun - Game Compatibility Checker", css="") as demo:
102
- # Header with logo
103
- gr.HTML(get_logo_html())
104
-
105
- # Main content
106
- with gr.Row():
107
- with gr.Column():
108
- game_input = gr.Textbox(label="Game Name", placeholder="Enter game name (e.g., Diablo 4)")
109
- check_btn = gr.Button("Check Compatibility", variant="primary")
110
- hw_btn = gr.Button("Detect Hardware", variant="secondary")
111
-
112
- with gr.Column():
113
- result_output = gr.Textbox(label="Results", lines=20)
114
-
115
- # Footer
116
- gr.HTML("""
117
- <div style="margin-top: 20px; text-align: center; padding: 10px; border-top: 1px solid #ddd;">
118
- <p>CanRun - Advanced Game Compatibility Checker with MCP Server Support</p>
119
- <p>Powered by G-Assist Integration</p>
120
- </div>
121
- """)
122
-
123
- # For async functions, we need to use .click(fn=..., inputs=..., outputs=...)
124
- check_btn.click(fn=analyze_game, inputs=game_input, outputs=result_output)
125
- hw_btn.click(fn=detect_hardware, inputs=None, outputs=result_output)
126
-
127
- return demo
128
-
129
- def is_mcp_available():
130
- """Check if the MCP package is available"""
131
- try:
132
- import mcp
133
- return True
134
- except ImportError:
135
- return False
136
-
137
- def main():
138
- """Main application entry point"""
139
- # Set up signal handlers
140
- signal.signal(signal.SIGINT, signal_handler)
141
- signal.signal(signal.SIGTERM, signal_handler)
142
-
143
- logger.info("Starting CanRun Game Compatibility Checker")
144
-
145
- # Create Gradio interface
146
- demo = create_gradio_interface()
147
-
148
- # Check if MCP support is available
149
- mcp_enabled = is_mcp_available()
150
- if mcp_enabled:
151
- logger.info("MCP server functionality is enabled")
152
- else:
153
- logger.info("MCP server functionality is disabled. Install with 'pip install \"gradio[mcp]\"' to enable")
154
-
155
- # Launch with auto port discovery
156
- launch_kwargs = {
157
- "server_name": "0.0.0.0",
158
- "share": False,
159
- "favicon_path": os.path.join(os.path.dirname(__file__), "logo.png"),
160
- }
161
-
162
- # Only enable MCP server if the package is available
163
- if mcp_enabled:
164
- launch_kwargs["mcp_server"] = True
165
-
166
- # Launch the server
167
- demo.queue().launch(**launch_kwargs)
168
-
169
- # Keep the main thread alive
170
- logger.info("Press Ctrl+C to stop the server")
171
- if hasattr(signal, 'pause'):
172
- # Unix systems
173
- signal.pause()
174
- else:
175
- # Windows systems
176
- while True:
177
- time.sleep(1)
178
-
179
- if __name__ == "__main__":
 
 
 
 
180
  main()
 
1
+ """
2
+ CanRun Game Compatibility Checker - Simple MCP Server Implementation
3
+ """
4
+
5
+ import gradio as gr
6
+ import logging
7
+ import os
8
+ import signal
9
+ import sys
10
+ import time
11
+ import asyncio
12
+ import base64
13
+ import platform
14
+
15
+ # Platform detection
16
+ IS_WINDOWS = platform.system() == "Windows"
17
+ from src.canrun_engine import CanRunEngine
18
+ from plugin import CanRunGAssistPlugin
19
+
20
+ # Configure logging
21
+ logging.basicConfig(
22
+ level=logging.INFO,
23
+ format="%(asctime)s - %(levelname)s - %(message)s",
24
+ handlers=[logging.StreamHandler(sys.stdout)]
25
+ )
26
+ logger = logging.getLogger(__name__)
27
+
28
+ def signal_handler(signum, frame):
29
+ """Handle shutdown signals gracefully."""
30
+ logger.info(f"Received signal {signum}, shutting down gracefully...")
31
+ sys.exit(0)
32
+
33
+ async def analyze_game(game_name):
34
+ """Analyze game compatibility using the CanRun engine"""
35
+ if not game_name:
36
+ return "Please enter a game name to begin the analysis."
37
+
38
+ try:
39
+ plugin = CanRunGAssistPlugin()
40
+ params = {"game_name": game_name, "force_refresh": True}
41
+ # Properly await the async method
42
+ response = await plugin.check_game_compatibility(params)
43
+
44
+ if response.get("success", False):
45
+ return response.get("message", "Analysis completed successfully.")
46
+ else:
47
+ return response.get("message", "Could not analyze the game. Please check the game name and try again.")
48
+ except Exception as e:
49
+ logger.error(f"Error analyzing game: {e}")
50
+ return f"An error occurred during analysis: {e}"
51
+
52
+ def detect_hardware():
53
+ """Detect hardware specifications"""
54
+ try:
55
+ plugin = CanRunGAssistPlugin()
56
+ response = plugin.detect_hardware({})
57
+
58
+ if response.get("success", False):
59
+ return response.get("message", "Hardware detection successful.")
60
+ else:
61
+ return response.get("message", "Could not detect hardware specifications.")
62
+ except Exception as e:
63
+ logger.error(f"Error detecting hardware: {e}")
64
+ return f"An error occurred during hardware detection: {e}"
65
+
66
+ def get_logo_html():
67
+ """Get HTML that displays the logo"""
68
+ logo_path = os.path.join(os.path.dirname(__file__), "logo.png")
69
+
70
+ if os.path.exists(logo_path):
71
+ # Read the logo file and encode it as base64
72
+ with open(logo_path, "rb") as image_file:
73
+ encoded_image = base64.b64encode(image_file.read()).decode("utf-8")
74
+
75
+ # Return HTML that displays the logo
76
+ return f"""
77
+ <div style="display: flex; align-items: center; margin-bottom: 0.5em">
78
+ <img src="data:image/png;base64,{encoded_image}" alt="CanRun Logo" style="height: 4em; margin-right: 1em;">
79
+ <div>
80
+ <h1 style="margin: 0; padding: 0">CanRun Game Compatibility Checker</h1>
81
+ <p style="margin: 0; padding: 0">Check if your PC can run any game with an advanced tier system and Steam API integration</p>
82
+ </div>
83
+ </div>
84
+ """
85
+ else:
86
+ logger.warning(f"Logo file not found at {logo_path}")
87
+ return """
88
+ <div>
89
+ <h1>CanRun Game Compatibility Checker</h1>
90
+ <p>Check if your PC can run any game with an advanced tier system and Steam API integration</p>
91
+ </div>
92
+ """
93
+
94
+ def create_gradio_interface():
95
+ """Create a simple Gradio interface with logo and favicon"""
96
+ # Set custom theme with brand color matching the logo
97
+ theme = gr.themes.Default(
98
+ primary_hue="green",
99
+ secondary_hue="gray",
100
+ )
101
+
102
+ # Define file paths
103
+ favicon_path = os.path.join(os.path.dirname(__file__), "logo.png")
104
+
105
+ with gr.Blocks(theme=theme, title="CanRun - Game Compatibility Checker", css="") as demo:
106
+ # Header with logo
107
+ gr.HTML(get_logo_html())
108
+
109
+ # Main content
110
+ with gr.Row():
111
+ with gr.Column():
112
+ game_input = gr.Textbox(label="Game Name", placeholder="Enter game name (e.g., Diablo 4)")
113
+ check_btn = gr.Button("Check Compatibility", variant="primary")
114
+ hw_btn = gr.Button("Detect Hardware", variant="secondary")
115
+
116
+ with gr.Column():
117
+ result_output = gr.Textbox(label="Results", lines=20)
118
+
119
+ # Footer
120
+ gr.HTML("""
121
+ <div style="margin-top: 20px; text-align: center; padding: 10px; border-top: 1px solid #ddd;">
122
+ <p>CanRun - Advanced Game Compatibility Checker with MCP Server Support</p>
123
+ <p>Powered by G-Assist Integration</p>
124
+ </div>
125
+ """)
126
+
127
+ # For async functions, we need to use .click(fn=..., inputs=..., outputs=...)
128
+ check_btn.click(fn=analyze_game, inputs=game_input, outputs=result_output)
129
+ hw_btn.click(fn=detect_hardware, inputs=None, outputs=result_output)
130
+
131
+ return demo
132
+
133
+ def is_mcp_available():
134
+ """Check if the MCP package is available"""
135
+ try:
136
+ import mcp
137
+ return True
138
+ except ImportError:
139
+ return False
140
+
141
+ def main():
142
+ """Main application entry point"""
143
+ # Set up signal handlers
144
+ signal.signal(signal.SIGINT, signal_handler)
145
+ signal.signal(signal.SIGTERM, signal_handler)
146
+
147
+ logger.info("Starting CanRun Game Compatibility Checker")
148
+
149
+ # Create Gradio interface
150
+ demo = create_gradio_interface()
151
+
152
+ # Check if MCP support is available
153
+ mcp_enabled = is_mcp_available()
154
+ if mcp_enabled:
155
+ logger.info("MCP server functionality is enabled")
156
+ else:
157
+ logger.info("MCP server functionality is disabled. Install with 'pip install \"gradio[mcp]\"' to enable")
158
+
159
+ # Launch with auto port discovery
160
+ launch_kwargs = {
161
+ "server_name": "0.0.0.0",
162
+ "share": False,
163
+ "favicon_path": os.path.join(os.path.dirname(__file__), "logo.png"),
164
+ }
165
+
166
+ # Only enable MCP server if the package is available
167
+ if mcp_enabled:
168
+ launch_kwargs["mcp_server"] = True
169
+
170
+ # Launch the server
171
+ demo.queue().launch(**launch_kwargs)
172
+
173
+ # Keep the main thread alive - Platform-independent approach
174
+ logger.info("Press Ctrl+C to stop the server")
175
+ try:
176
+ # This works on most systems and is more reliable than signal.pause()
177
+ while True:
178
+ time.sleep(1)
179
+ except KeyboardInterrupt:
180
+ logger.info("Keyboard interrupt received, shutting down...")
181
+ sys.exit(0)
182
+
183
+ if __name__ == "__main__":
184
  main()