Allow EloTracker to run matches for multiple games
parent
e2daa9a205
commit
ca7bfdc50a
8
elo.py
8
elo.py
|
|
@ -3,7 +3,7 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from elo_tracker import EloTracker
|
from elo_tracker import EloTracker
|
||||||
from pyclient.games import TicTacToe
|
from pyclient.games import RoyalGameOfUr, TicTacToe
|
||||||
|
|
||||||
GAME_FILE = "games.jsonl"
|
GAME_FILE = "games.jsonl"
|
||||||
PLAYER_FILE = "known_players.json"
|
PLAYER_FILE = "known_players.json"
|
||||||
|
|
@ -21,6 +21,12 @@ def main() -> int:
|
||||||
player_count=2,
|
player_count=2,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
tracker.start_periodic_matches(
|
||||||
|
game=RoyalGameOfUr.empty(),
|
||||||
|
interval_seconds=9 * 60,
|
||||||
|
player_count=2,
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tracker.start_server(import_name=__name__)
|
tracker.start_server(import_name=__name__)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ from typing import Any, Sequence
|
||||||
|
|
||||||
import agents
|
import agents
|
||||||
import pyclient
|
import pyclient
|
||||||
|
import time
|
||||||
|
|
||||||
from pyclient.games import FinishState, Game
|
from pyclient.games import FinishState, Game
|
||||||
|
|
||||||
|
|
@ -280,7 +281,7 @@ class EloTracker:
|
||||||
# Threading variables
|
# Threading variables
|
||||||
self.__lock = threading.RLock()
|
self.__lock = threading.RLock()
|
||||||
self.__scheduler_stop = threading.Event()
|
self.__scheduler_stop = threading.Event()
|
||||||
self.__scheduler_thread: threading.Thread | None = None
|
self.__scheduler_threads: list[threading.Thread] = []
|
||||||
|
|
||||||
# Immutable values
|
# Immutable values
|
||||||
self.debug: bool = debug
|
self.debug: bool = debug
|
||||||
|
|
@ -551,7 +552,11 @@ class EloTracker:
|
||||||
:rtype: bool
|
:rtype: bool
|
||||||
"""
|
"""
|
||||||
with self.__lock:
|
with self.__lock:
|
||||||
return self.__scheduler_thread is not None and self.__scheduler_thread.is_alive()
|
for thread in self.__scheduler_threads:
|
||||||
|
if thread.is_alive():
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def load_players(self) -> None:
|
def load_players(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
@ -665,33 +670,40 @@ class EloTracker:
|
||||||
raise ValueError("player_count must be greater than one.")
|
raise ValueError("player_count must be greater than one.")
|
||||||
|
|
||||||
with self.__lock:
|
with self.__lock:
|
||||||
if self.is_running_periodic_matches():
|
|
||||||
self.stop_periodic_matches()
|
|
||||||
|
|
||||||
self.__scheduler_stop.clear()
|
self.__scheduler_stop.clear()
|
||||||
self.__scheduler_thread = threading.Thread(
|
thread = threading.Thread(
|
||||||
target=self.__scheduler_loop,
|
target=self.__scheduler_loop,
|
||||||
args=(game, interval_seconds, player_count),
|
args=(game, interval_seconds, player_count),
|
||||||
daemon=True,
|
daemon=True,
|
||||||
)
|
)
|
||||||
self.__scheduler_thread.start()
|
self.__scheduler_threads.append(thread)
|
||||||
|
thread.start()
|
||||||
|
|
||||||
def stop_periodic_matches(self) -> None:
|
def stop_periodic_matches(self) -> None:
|
||||||
"""
|
"""
|
||||||
Stop the periodic match scheduler and wait briefly for it to exit.
|
Stop the periodic match scheduler and wait briefly for it to exit.
|
||||||
"""
|
"""
|
||||||
thread: threading.Thread | None
|
max_wait_time_s = 5
|
||||||
|
now = time.time()
|
||||||
|
time_left = lambda : max(0.1, now + max_wait_time_s - time.time())
|
||||||
|
to_remove : list[threading.Thread] = []
|
||||||
|
|
||||||
|
# Announce that all threads need to be stopped
|
||||||
with self.__lock:
|
with self.__lock:
|
||||||
self.__scheduler_stop.set()
|
self.__scheduler_stop.set()
|
||||||
thread = self.__scheduler_thread
|
to_remove = [ thread for thread in self.__scheduler_threads ]
|
||||||
|
|
||||||
|
# Then, quietly remove all existing threads
|
||||||
|
for thread in self.__scheduler_threads:
|
||||||
if thread is not None:
|
if thread is not None:
|
||||||
thread.join(timeout=5)
|
thread.join(timeout=time_left())
|
||||||
|
|
||||||
|
# Remove all stopped threads
|
||||||
|
# Keep in mind that another threads might've added new threads in the
|
||||||
|
# meantime.
|
||||||
with self.__lock:
|
with self.__lock:
|
||||||
if self.__scheduler_thread is thread:
|
for thread in to_remove:
|
||||||
self.__scheduler_thread = None
|
self.__scheduler_threads.remove(thread)
|
||||||
|
|
||||||
def get_json_players(self, game_name : str) -> list[dict[str, Any]]:
|
def get_json_players(self, game_name : str) -> list[dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue