Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.idea/.gitignore
.idea/misc.xml
.idea/modules.xml
.idea/sample-playmaker-server-python-thrift.iml
.idea/vcs.xml
.idea/inspectionProfiles/profiles_settings.xml
.idea/inspectionProfiles/Project_Default.xml
venv/
.venv/
utils/__pycache__/PFProcessServer.cpython-310.pyc
soccer/__pycache__/
scripts/proxy
scripts/rcssserver
__pycache__/
20 changes: 20 additions & 0 deletions check_requirements.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

import pkg_resources
import sys

def check_requirements(requirements_file='requirements.txt'):
with open(requirements_file, 'r') as file:
requirements = file.readlines()

for requirement in requirements:
requirement = requirement.strip()
try:
pkg_resources.require(requirement)
except pkg_resources.VersionConflict as e:
print(f"WARNING: {str(e)}")
except pkg_resources.DistributionNotFound as e:
print(f"ERROR: {str(e)}")
sys.exit(1)

if __name__ == "__main__":
check_requirements()
38 changes: 38 additions & 0 deletions scripts/download-proxy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/bin/sh

# check proxy directory exists, if exists, remove it
if [ -d proxy ]; then
echo "proxy directory exists, remove it"
rm -rf proxy
fi

mkdir proxy

cd proxy

# Check if curl exists
if command -v curl >/dev/null 2>&1; then
echo "curl is installed."
else
echo "curl is not installed. Please install it."
exit 1
fi

# Check if get exists
if command -v wget >/dev/null 2>&1; then
echo "wget is installed."
else
echo "wget is not installed. Please install it."
exit 1
fi

# download soccer simulation proxy
wget $(curl -s "https://api.github.com/repos/clsframework/soccer-simulation-proxy/releases/latest" | grep -oP '"browser_download_url": "\K[^"]*' | grep "soccer-simulation-proxy.tar.gz")

tar -xvf soccer-simulation-proxy.tar.gz

mv soccer-simulation-proxy/* .

rm -rf soccer-simulation-proxy

rm soccer-simulation-proxy.tar.gz
40 changes: 40 additions & 0 deletions scripts/download-rcssserver.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/sh

# check rcssserver directory exists, if exists, remove it
if [ -d rcssserver ]; then
echo "rcssserver directory exists, remove it"
rm -rf rcssserver
fi

mkdir rcssserver

cd rcssserver

# Check if curl exists
if command -v curl >/dev/null 2>&1; then
echo "curl is installed."
else
echo "curl is not installed. Please install it."
exit 1
fi

# Check if get exists
if command -v wget >/dev/null 2>&1; then
echo "wget is installed."
else
echo "wget is not installed. Please install it."
exit 1
fi

# download soccer simulation server App Image
wget $(curl -s https://api.github.com/repos/clsframework/rcssserver/releases/latest | grep -oP '"browser_download_url": "\K(.*rcssserver-x86_64-.*\.AppImage)' | head -n 1)

# check download is successful
if [ ! -f *.AppImage ]; then
echo "Download failed"
exit 1
fi

mv rcssserver-x86_64-*.AppImage rcssserver

chmod +x rcssserver
7 changes: 6 additions & 1 deletion server.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
from multiprocessing import Manager, Lock
import logging
from pyrusgeom.vector_2d import Vector2D
import argparse


logging.basicConfig(level=logging.DEBUG)

Expand Down Expand Up @@ -161,4 +163,7 @@ def serve(port):


if __name__ == '__main__':
serve(50051)
parser = argparse.ArgumentParser(description='Run play maker server')
parser.add_argument('-p', '--g-port', required=False, help='The port of the server', default=50051)
args = parser.parse_args()
serve(args.g_port)
85 changes: 85 additions & 0 deletions start-team.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import subprocess
import os
import signal
import threading
import logging
import argparse
import check_requirements


# Set up logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')

def run_server_script(args):
# Start the server.py script as a new process group
process = subprocess.Popen(
['python3', 'server.py', '--g-port', args.g_port],
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are using python, why create a separate process?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to make it similar to start-team.sh

preexec_fn=os.setsid, # Create a new session and set the process group ID
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT # Capture stderr and redirect it to stdout
)
return process

def run_start_script(args):
# Start the start.sh script in its own directory as a new process group
process = subprocess.Popen(
['bash', 'start.sh', '-t', args.team_name, '--g-port', args.g_port],
cwd='scripts/proxy', # Corrected directory to where start.sh is located
preexec_fn=os.setsid, # Create a new session and set the process group ID
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT # Capture stderr and redirect it to stdout
)
return process

def stream_output(process, prefix):
# Stream output from the process and log it with a prefix
for line in iter(process.stdout.readline, b''):
logging.debug(f'{prefix} {line.decode().strip()}')
process.stdout.close()

def kill_process_group(process):
try:
os.killpg(os.getpgid(process.pid), signal.SIGTERM) # Send SIGTERM to the process group
except ProcessLookupError:
pass # The process might have already exited

if __name__ == "__main__":
# Set up argument parsing
parser = argparse.ArgumentParser(description='Run server and team scripts.')
parser.add_argument('-t', '--team_name', required=False, help='The name of the team', default='CLS')
parser.add_argument('--g-port', required=False, help='The port of the server', default='50051')
args = parser.parse_args()

try:
# Check Python requirements
logging.debug("Checking Python requirements...")
check_requirements.check_requirements()

# Run the server.py script first
server_process = run_server_script(args)
logging.debug(f"Started server.py process with PID: {server_process.pid}")

# Run the start.sh script after server.py with the given arguments
start_process = run_start_script(args)
logging.debug(f"Started start.sh process with PID: {start_process.pid} with team name {args=}")

# Monitor both processes and log their outputs
server_thread = threading.Thread(target=stream_output, args=(server_process, 'server:'))
start_thread = threading.Thread(target=stream_output, args=(start_process, 'team:'))

server_thread.start()
start_thread.start()

# Wait for both threads to finish
server_thread.join()
start_thread.join()

except KeyboardInterrupt:
logging.debug("Interrupted! Killing all processes.")
kill_process_group(server_process)
kill_process_group(start_process)

finally:
# Ensure all processes are killed on exit
kill_process_group(server_process)
kill_process_group(start_process)
76 changes: 76 additions & 0 deletions start-team.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/bin/bash

# Ensure the script exits if any command fails
set -e
# check scripts/proxy directory does not exist, raise error
if [! -d scripts/proxy ]; then
echo "scripts/proxy directory does not exist"
exit 1
fi

team_name="CLS"
g_port=50051

# help function
usage() {
echo "Usage: $0 [options]"
echo "Options:"
echo " -t team_name: specify team name"
echo " --g-port GRPC PORT - specifies grpc port (default: 50051)"
exit 1
}

while [ $# -gt 0 ]
do
case $1 in
-t)
team_name=$2
shift
;;
--g-port)
g_port=$2
shift
;;
*)
echo 1>&2
echo "invalid option \"${1}\"." 1>&2
echo 1>&2
usage
exit 1
;;
esac

shift 1
done

# Check Python requirements
echo "Checking Python requirements..."
python3 check_requirements.py

# Start server.py in the background
echo "Starting server.py..."
python3 server.py --g-port $g_port &
server_pid=$!

# Function to kill server and team processes on exit
cleanup() {
echo "Cleaning up..."
kill $server_pid
kill $start_pid
}

# Trap the exit signal to cleanup processes
trap cleanup EXIT

# Wait a moment to ensure the server has started (optional)
sleep 2

# Start start.sh script in the correct directory with arguments
echo "Starting start.sh with team name: $team_name and ..."
cd scripts/proxy
bash start.sh -t "$team_name" --g-port $g_port &
start_pid=$!

# Wait for both background processes to finish
wait $server_pid
wait $start_pid