Spaces:
Sleeping
Sleeping
| import subprocess | |
| import os | |
| import sys | |
| import time | |
| def kill_port_8000(): | |
| try: | |
| if os.name == "nt": # Windows | |
| # Find PID on port 8000 | |
| result = subprocess.run(["netstat", "-ano"], capture_output=True, text=True) | |
| for line in result.stdout.splitlines(): | |
| if ":8000" in line and "LISTENING" in line: | |
| parts = line.split() | |
| pid = parts[-1] | |
| print(f"Killing process {pid} on port 8000...") | |
| subprocess.run(["taskkill", "/F", "/PID", pid], check=False) | |
| time.sleep(1) | |
| else: # Linux/Mac | |
| # Use lsof on macOS, fuser on Linux | |
| import platform | |
| system = platform.system() | |
| if system == "Darwin": # macOS | |
| result = subprocess.run( | |
| ["lsof", "-ti", "tcp:8000"], capture_output=True, text=True | |
| ) | |
| pids = result.stdout.strip().split("\n") | |
| for pid in pids: | |
| if pid: | |
| print(f"Killing process {pid} on port 8000...") | |
| subprocess.run(["kill", "-9", pid], check=False) | |
| else: # Linux | |
| subprocess.run(["fuser", "-k", "8000/tcp"], check=False) | |
| except Exception as e: | |
| print(f"Error killing port: {e}") | |
| import argparse | |
| def run_server(): | |
| parser = argparse.ArgumentParser(description="Run the ATC Simulation Server") | |
| parser.add_argument( | |
| "--ui", "-u", action="store_true", help="Start the backend and the frontend UI" | |
| ) | |
| parser.add_argument( | |
| "--only-ui", action="store_true", help="Start ONLY the frontend UI (visualizer)" | |
| ) | |
| args = parser.parse_args() | |
| script_dir = os.path.dirname(os.path.abspath(__file__)) | |
| parent_dir = os.path.dirname(script_dir) | |
| ui_dir = os.path.join(script_dir, "visualizer") | |
| # Detect pnpm or npm | |
| def get_pkg_manager(): | |
| # Check if pnpm is available | |
| try: | |
| subprocess.run(["pnpm", "--version"], capture_output=True, shell=True, check=True) | |
| return "pnpm" | |
| except (subprocess.CalledProcessError, FileNotFoundError): | |
| return "npm" | |
| pkg_manager = get_pkg_manager() | |
| print(f"Using {pkg_manager} for frontend...") | |
| if args.only_ui: | |
| print("Starting ONLY Frontend (Vite)...") | |
| try: | |
| subprocess.run([pkg_manager, "run", "dev"], cwd=ui_dir, shell=True) | |
| except KeyboardInterrupt: | |
| print("\nStopping UI...") | |
| return | |
| kill_port_8000() | |
| # Start UI if flag provided | |
| ui_process = None | |
| if args.ui: | |
| print("Starting Frontend (Vite)...") | |
| try: | |
| ui_process = subprocess.Popen([pkg_manager, "run", "dev"], cwd=ui_dir, shell=True) | |
| print(f"Frontend process started (PID: {ui_process.pid})") | |
| except Exception as e: | |
| print(f"Error starting frontend: {e}") | |
| print("Starting backend...") | |
| env = os.environ.copy() | |
| if "PYTHONPATH" in env: | |
| env["PYTHONPATH"] = parent_dir + os.pathsep + env["PYTHONPATH"] | |
| else: | |
| env["PYTHONPATH"] = parent_dir | |
| try: | |
| subprocess.run( | |
| [ | |
| sys.executable, | |
| "-m", | |
| "uvicorn", | |
| "atc_rl_api.api.main:app", | |
| "--host", | |
| "0.0.0.0", | |
| "--port", | |
| "8000", | |
| ], | |
| env=env, | |
| ) | |
| except KeyboardInterrupt: | |
| print("\nStopping server...") | |
| finally: | |
| if ui_process: | |
| print("Terminating frontend process...") | |
| ui_process.terminate() | |
| ui_process.wait() | |
| if __name__ == "__main__": | |
| run_server() | |