"""Public client entry points.""" from typing import List, Optional import requests from .poll import ServerAgent class PyClient: """Host games between discovered server agents.""" def __init__(self, hosts: List[str]) -> None: """ Create a PyClient. :param hosts: URLs of servers that can participate. :type hosts: List[str] :raises ValueError: If no reachable servers are provided. """ self.agents: List[ServerAgent] = [] self.hosts: List[str] = [] for host in hosts: agent = self.__discover_host(host) if agent is not None: self.agents.append(agent) self.hosts.append(agent.url) if len(self.hosts) <= 0: raise ValueError( "No valid hosts found! Check your internet connection or verify the URLs are correct." ) def __discover_host(self, url: str) -> Optional[ServerAgent]: try: return ServerAgent.from_url(url) except (requests.exceptions.RequestException, ValueError): return None def play_game(self, name : str, game, timeout : float = 1.0): """ Play a given game. Ask the registered agents to participate. """ states = [] current_state = game.empty() while current_state.winner() is None: player : int = current_state.player_to_move() if len(self.agents) < player: raise KeyError( f"The client does not have access to {player} players" ) # Ask for move agent = self.agents[player] payload = agent.poll( game=current_state.action_name(), payload=current_state.to_dict(), timeout=timeout, ) # Calculate move current_state = current_state.move(payload) # Save the results states.append((player, payload, current_state)) return states def verify_host(self, url: str) -> bool: """ Verify whether the URL seems to contain a link to a playable server. """ return self.__discover_host(url) is not None __all__ = ["PyClient", "ServerAgent"]