class SoccerMatch(Savable): """ Match de foot. """ def __init__(self, team1=None, team2=None, max_steps=settings.MAX_GAME_STEPS, states=None): """ :param team1: premiere equipe :param team2: deuxieme equipe :return: """ self._team1, self._team2, self.max_steps = team1, team2, max_steps self._listeners = SoccerEvents() self._state = None # SoccerState.create_initial_state(self._team1.nb_players,self._team2.nb_players) self._thread = None self._on_going = False self._lock = Lock() self._kill = False self._replay = False self._step_replay = 0 self._states = [] # [self.state] self.strats = [] if states: self.states = states @property def state(self): """ :return: etat courant """ return self._state @property def states(self): return self._states @states.setter def states(self, list_states): self._states = list_states self._state = self._states[0] self._replay = True self._on_going = False @property def team1(self): return self._team1 @property def team2(self): return self._team2 def play(self, join=True): """ joue le match :param join: attend que le match soit fini avant de sortir :return: """ if not self._thread or not self._thread.isAlive(): self._thread = threading.Thread(target=self._play) self._thread.start() if join: self._thread.join() return self.state.score_team1, self.state.score_team2 return (None, None) def reset(self): self.kill() self._state = None self._step_replay = 0 if not self._replay: self._states = [] self._thread = None self._on_going = False def get_score(self, idx): if self.state is None: return 0 return self.state.get_score_team(idx) def get_team(self, i): if i == 1: return self.team1 if i == 2: return self.team2 return None def kill(self): """ arrete le match :return: """ self._kill = True time.sleep(0.1) self._kill = False def _next_step(self): self._lock.acquire() if not self._on_going: self._lock.release() return if self._replay: self._step_replay += 1 if self._step_replay >= len(self._states): self._lock.release() return if self._state.winning_team > 0: self._listeners.end_round(self.team1, self.team2, self.state) if self._replay: self._state = self._states[self._step_replay] else: self._state.reset_state() self._listeners.begin_round(self.team1, self.team2, self.state) self._lock.release() return if self._replay: self._state = self._states[self._step_replay] else: actions = None try: actions = self.team1.compute_strategies(self.state, 1) except Exception as e: print(e) self._state.step = self.max_steps self._state._score[2] += 10 print("Error for team 1 -- loose match") if self.team2: try: actions.update(self.team2.compute_strategies( self.state, 2)) except Exception as e: print(e) self._state.step = self.max_steps self._state._score[1] += 10 print("Error for team 2 -- loose match") self._state.apply_actions(actions) self._lock.release() def _begin_match(self): if self._on_going: return self._on_going = True if self._replay: self._step_replay = 0 self._state = self._states[self._step_replay] self._listeners.begin_match(self.team1, self.team2, self.state) self._listeners.begin_round(self.team1, self.team2, self.state) return self._state = SoccerState.create_initial_state(self._team1.nb_players, self._team2.nb_players) self._states = [self.state.copy()] self.strats = [(tuple(str(x) for x in self.team1.strategies), tuple(str(x) for x in self.team2.strategies))] self._listeners.begin_match(self.team1, self.team2, self.state) self._listeners.begin_round(self.team1, self.team2, self.state) for s in self.team1.strategies + self.team2.strategies: self._listeners += s def _play(self): if not self._thread or self._on_going: return self._begin_match() while not self._kill and ((not self._replay and self._state.step < self.max_steps) or \ (self._replay and self._step_replay < len(self._states) - 1)): self._next_step() if not self._replay: self._states.append(self.state.copy()) self.strats.append( (tuple(str(x) for x in self.team1.strategies), tuple(str(x) for x in self.team2.strategies))) self._listeners.update_round(self.team1, self.team2, self.state) self._on_going = False self._replay = True self._listeners.end_match(self.team1, self.team2, self.state) def send_to_strategies(self, cmd): self._lock.acquire() if self.team1: for (i, s) in enumerate(self.team1.strategies): if hasattr(s, "listen"): s.listen(cmd, 1, i) if self.team2: for (i, s) in enumerate(self.team2.strategies): if hasattr(s, "listen"): s.listen(cmd, 2, i) self._lock.release() def __str__(self): return "%s-%s (%d,%d)" % (self.team1, self.team2, self.get_score(1), self.get_score(2)) def copy(self): return deepcopy(self) def to_str(self): return "%s\n%s\n%s" % (str(self.team1), str(self.team2), "\n".join( str(s) for s in self._states)) @classmethod def from_str(cls, strg): l_tmp = strg.split("\n") res = cls(SoccerTeam.from_str(l_tmp[0]), SoccerTeam.from_str(l_tmp[1])) res._states = [ SoccerState.from_str(x) for x in l_tmp[2:] if len(x) > 0 ] if len(res._states) > 0: res._state = res._states[-1] else: res._state = SoccerState.create_initial_state( res.team1.nb_players, res.team2.nb_players) res._replay = True return res
class SoccerTournament(Savable): TeamTuple = namedtuple("TeamTuple", ["team", "score"]) SEP_MATCH = "#####MATCH#####\n" def __init__(self, nb_players=None, max_steps=settings.MAX_GAME_STEPS, retour=True): self.nb_players, self.max_steps, self._retour = nb_players, max_steps, retour self._matches = dict() self._teams = [] self._listeners = SoccerEvents() self.cur_match, self._list_matches = None, None self._over, self._on_going = False, False self.cur_i, self.cur_j = -1, -1 self.verbose = True self._kill = False self._replay = False self._join = True def add_team(self, team, score=None): if score is None: score = Score() if self.nb_players and self.nb_players != team.nb_players: return False self._teams.append(self.TeamTuple(team, score)) if self.nb_teams > 1: for i, t in enumerate(self.teams[:-1]): self._matches[(i, self.nb_teams - 1)] = SoccerMatch(t, team, self.max_steps) if self._retour: self._matches[(self.nb_teams - 1, i)] = SoccerMatch(team, t, self.max_steps) return True def get_team(self, i): if type(i) == str: i = self.find_team(i) return self._teams[i].team def reset(self): self.cur_match = None self._list_matches = None self._on_going = False for t in self._teams: t.score.set() for m in self._matches.values(): m.reset() @property def nb_teams(self): return len(self.teams) @property def teams(self): return [t.team for t in self._teams] @property def nb_matches(self): return len(self._matches) def play(self, join=True): if self._on_going: return self._on_going = True self._join = join self._list_matches = sorted(self._matches.items()) self.play_next() def kill(self): self._kill = True if hasattr(self.cur_match, "kill"): self.cur_match.kill() def play_next(self): if len(self._list_matches) == 0 or self._kill: self._on_going = False self._kill = False if self.verbose: print("Fin tournoi") return (self.cur_i, self.cur_j), self.cur_match = self._list_matches.pop(0) self.cur_match._listeners += self self.cur_match.play(self._join) def find_team(self, name): for i, t in enumerate(self._teams): if t.team.name == name: return i return -1 def get_score(self, i): return self._teams[i].score def get_match(self, i, j): if type(i) == str and type(j) == str: i = self.find_team(i) j = self.find_team(j) return self._matches[(i, j)] def get_matches(self, i): if type(i) == str: i = self.find_team(i) return [m for k, m in self._matches.items() if k[0] == i or k[1] == i] def format_scores(self): sc = sorted([(t.score, t.team) for t in self._teams], reverse=True) res = ["\033[92m%s\033[0m (\033[93m%s\033[m) : %s" % (team.name, team.login, str(score)) for score, team in sc] return "\033[93m***\033[0m \033[95m Resultats pour le tournoi \033[92m%d joueurs\033[0m : \033[93m***\33[0m \n\t%s\n\n" % \ (self.nb_teams, "\n\t".join(res)) def to_str(self): res = "%d|%d|%d\n" % ( self.nb_players if self.nb_players is not None else 0, len(self._teams), int(self._retour)) res += "\n".join( "%d,%s\n%s" % (i, team.score.to_str(), team.team.to_str()) for i, team in enumerate(self._teams)) res += "\n%s" % (self.SEP_MATCH,) res += self.SEP_MATCH.join("%d,%d\n%s\n" % (k[0], k[1], match) for k, match in sorted(self._matches.items())) return res @classmethod def from_str(cls, strg): res = cls() l_strg = strg.split(cls.SEP_MATCH) cur_l = l_strg[0].split("\n") res.nb_players, nb_teams, res._retour = [int(x) for x in cur_l.pop(0).split("|")] while len(cur_l) > 0: info = cur_l.pop(0) if len(info) == 0: continue fvir = info.index(",") idx, sc_str = info[:fvir], info[fvir + 1:] assert (len(res._teams) == int(idx)) score = Score.from_str(sc_str) team = SoccerTeam.from_str(cur_l.pop(0)) res.add_team(team, score) for l in l_strg[1:]: if len(l) == 0: continue t1 = int(l[:l.index(",")]) t2 = int(l[l.index(",") + 1:l.index("\n")]) match = SoccerMatch.from_str(l[l.index("\n") + 1:]) res._matches[(t1, t2)] = match res._replay = True return res def update_round(self, *args, **kwargs): self._listeners.update_round(*args, **kwargs) def begin_match(self, *args, **kwargs): if self.verbose: print("Debut match %d/%d : %s vs %s" % (self.nb_matches - len(self._list_matches), self.nb_matches, self.cur_match.get_team(1).name, self.cur_match.get_team(2).name)) self._listeners.begin_match(*args, **kwargs) def begin_round(self, *args, **kwargs): self._listeners.begin_round(*args, **kwargs) def end_round(self, *args, **kwargs): self._listeners.end_round(*args, **kwargs) def end_match(self, *args, **kwargs): if not self._replay: self._teams[self.cur_i].score.add(self.cur_match.get_score(1), self.cur_match.get_score(2)) self._teams[self.cur_j].score.add(self.cur_match.get_score(2), self.cur_match.get_score(1)) if self.verbose: print("Fin match %s vs %s : %d - %d" % (self.cur_match.get_team(1).name, self.cur_match.get_team(2).name, \ self.cur_match.get_score(1), self.cur_match.get_score(2))) self._listeners.end_match(*args, **kwargs) self.cur_match._listeners -= self self.play_next()
class SoccerTournament(Savable): TeamTuple = namedtuple("TeamTuple", ["team", "score"]) SEP_MATCH = "#####MATCH#####\n" def __init__(self, nb_players=None, max_steps=settings.MAX_GAME_STEPS, retour=True, verbose=True): self.nb_players, self.max_steps, self._retour = nb_players, max_steps, retour self._matches = dict() self._teams = [] self._listeners = SoccerEvents() self.cur_match, self._list_matches = None, None self._over, self._on_going = False, False self.cur_i, self.cur_j = -1, -1 self.verbose = verbose self._kill = False self._replay = False self._join = True def add_team(self, team, score=None): if score is None: score = Score() if self.nb_players and self.nb_players != team.nb_players: return False self._teams.append(self.TeamTuple(team, score)) if self.nb_teams > 1: for i, t in enumerate(self.teams[:-1]): self._matches[(i, self.nb_teams - 1)] = SoccerMatch( t, team, self.max_steps) if self._retour: self._matches[(self.nb_teams - 1, i)] = SoccerMatch(team, t, self.max_steps) return True def get_team(self, i): if type(i) == str: i = self.find_team(i) return self._teams[i].team def reset(self): self.cur_match = None self._list_matches = None self._on_going = False for t in self._teams: t.score.set() for m in self._matches.values(): m.reset() self._kill = False self._replay = False @property def nb_teams(self): return len(self.teams) @property def teams(self): return [t.team for t in self._teams] @property def nb_matches(self): return len(self._matches) def play(self, join=True): if self._on_going: return for m in self._matches.values(): m.max_steps = self.max_steps self._on_going = True self._join = join self._list_matches = sorted(self._matches.items()) self.play_next() def kill(self): self._kill = True if hasattr(self.cur_match, "kill"): self.cur_match.kill() def play_next(self): if len(self._list_matches) == 0 or self._kill: self._on_going = False self._kill = False if self.verbose: print("Fin tournoi") return (self.cur_i, self.cur_j), self.cur_match = self._list_matches.pop(0) self.cur_match._listeners += self self.cur_match.play(self._join) def find_team(self, name): for i, t in enumerate(self._teams): if t.team.name == name: return i return -1 def get_score(self, i): return self._teams[i].score def get_match(self, i, j): if type(i) == str and type(j) == str: i = self.find_team(i) j = self.find_team(j) return self._matches[(i, j)] def get_matches(self, i): if type(i) == str: i = self.find_team(i) return [m for k, m in self._matches.items() if k[0] == i or k[1] == i] def format_scores(self): sc = sorted([(t.score, t.team) for t in self._teams], reverse=True) res = [ "\033[92m%s\033[0m (\033[93m%s\033[m) : %s" % (team.name, team.login, str(score)) for score, team in sc ] return "\033[93m***\033[0m \033[95m Resultats pour le tournoi \033[92m%d joueurs\033[0m : \033[93m***\33[0m \n\t%s\n\n" % \ (self.nb_teams, "\n\t".join(res)) def __str__(self): return "Tournoi %d joueurs, %d equipes, %d matches" % ( self.nb_players, self.nb_teams, self.nb_matches) def to_str(self): res = "%d|%d|%d\n" % (self.nb_players if self.nb_players is not None else 0, len(self._teams), int(self._retour)) res += "\n".join("%d,%s\n%s" % (i, team.score.to_str(), team.team.to_str()) for i, team in enumerate(self._teams)) res += "\n%s" % (self.SEP_MATCH, ) res += self.SEP_MATCH.join( "%d,%d\n%s\n" % (k[0], k[1], match.to_str()) for k, match in sorted(self._matches.items())) return res @classmethod def load(cls, filename): res = None if zipfile.is_zipfile(filename): zf = zipfile.ZipFile(filename) fn = zf.infolist()[0].filename res = cls.from_str(zf.read(fn)) return res with open(filename, "r") as f: res = cls.from_str(f.read()) return res @classmethod def from_str(cls, strg): res = cls() l_strg = strg.split(cls.SEP_MATCH) cur_l = l_strg[0].split("\n") res.nb_players, nb_teams, res._retour = [ int(x) for x in cur_l.pop(0).split("|") ] while len(cur_l) > 0: info = cur_l.pop(0) if len(info) == 0: continue fvir = info.index(",") idx, sc_str = info[:fvir], info[fvir + 1:] assert (len(res._teams) == int(idx)) score = Score.from_str(sc_str) team = SoccerTeam.from_str(cur_l.pop(0)) res.add_team(team, score) for l in l_strg[1:]: if len(l) == 0: continue t1 = int(l[:l.index(",")]) t2 = int(l[l.index(",") + 1:l.index("\n")]) match = SoccerMatch.from_str(l[l.index("\n") + 1:]) res._matches[(t1, t2)] = match res._replay = True return res def update_round(self, *args, **kwargs): self._listeners.update_round(*args, **kwargs) def begin_match(self, *args, **kwargs): if self.verbose: print("Debut match %d/%d : %s (%s) vs %s (%s)" % (self.nb_matches - len(self._list_matches), self.nb_matches, self.cur_match.get_team(1).name, self.cur_match.get_team(1).login, self.cur_match.get_team(2).name, self.cur_match.get_team(2).login)) self._listeners.begin_match(*args, **kwargs) def begin_round(self, *args, **kwargs): self._listeners.begin_round(*args, **kwargs) def end_round(self, *args, **kwargs): self._listeners.end_round(*args, **kwargs) def end_match(self, *args, **kwargs): if not self._replay: self._teams[self.cur_i].score.add(self.cur_match.get_score(1), self.cur_match.get_score(2)) self._teams[self.cur_j].score.add(self.cur_match.get_score(2), self.cur_match.get_score(1)) if self.verbose: print("Fin match %s vs %s : %d - %d" % (self.cur_match.get_team(1).name, self.cur_match.get_team(2).name, \ self.cur_match.get_score(1), self.cur_match.get_score(2))) self._listeners.end_match(*args, **kwargs) self.cur_match._listeners -= self self.play_next()
class SoccerMatch(Savable): """ Match de foot. """ def __init__(self, team1=None, team2=None, max_steps=settings.MAX_GAME_STEPS): """ :param team1: premiere equipe :param team2: deuxieme equipe :return: """ self._team1, self._team2, self.max_steps = team1, team2, max_steps self._listeners = SoccerEvents() self._state = None # SoccerState.create_initial_state(self._team1.nb_players,self._team2.nb_players) self._states = [] # [self.state] self._thread = None self._on_going = False self._lock = Lock() self._kill = False self._replay = False self._step_replay = 0 @property def state(self): """ :return: etat courant """ return self._state.copy() @property def team1(self): return self._team1 @property def team2(self): return self._team2 def play(self, join=True): """ joue le match :param join: attend que le match soit fini avant de sortir :return: """ if not self._thread or not self._thread.isAlive(): self._thread = threading.Thread(target=self._play) self._thread.start() if join: self._thread.join() return self.state.score_team1, self.state.score_team2 return (None, None) def reset(self): self.kill() self._state = None self._step_replay = 0 if not self._replay: self._states = [] self._thread = None self._on_going = False def get_score(self, idx): return self.state.get_score_team(idx) def get_team(self, i): if i == 1: return self.team1 if i == 2: return self.team2 return None def kill(self): """ arrete le match :return: """ self._kill = True time.sleep(0.1) self._kill = False def _next_step(self): self._lock.acquire() if not self._on_going: self._lock.release() return if self._replay: self._step_replay += 1 if self._step_replay >= len(self._states): self._lock.release() return if self._state.winning_team > 0: self._listeners.end_round(self.team1, self.team2, self.state) if self._replay: self._state = self._states[self._step_replay] else: self._state.reset_state() self._listeners.begin_round(self.team1, self.team2, self.state) self._lock.release() return if self._replay: self._state = self._states[self._step_replay] else: actions = self.team1.compute_strategies(self.state, 1) actions.update(self.team2.compute_strategies(self.state, 2)) self._state.apply_actions(actions) self._lock.release() def _begin_match(self): if self._on_going: return self._on_going = True if self._replay: self._step_replay = 0 self._state = self._states[self._step_replay] self._listeners.begin_match(self.team1, self.team2, self.state) self._listeners.begin_round(self.team1, self.team2, self.state) return self._state = SoccerState.create_initial_state(self._team1.nb_players, self._team2.nb_players) self._states = [self.state] self._listeners.begin_match(self.team1, self.team2, self.state) self._listeners.begin_round(self.team1, self.team2, self.state) for s in self.team1.strategies + self.team2.strategies: self._listeners += s def _play(self): if not self._thread or self._on_going: return self._begin_match() while not self._kill and ((not self._replay and self._state.step < self.max_steps) or \ (self._replay and self._step_replay < len(self._states) - 1)): self._next_step() if not self._replay: self._states.append(self.state) self._listeners.update_round(self.team1, self.team2, self.state) self._on_going = False self._replay = True self._listeners.end_match(self.team1, self.team2, self.state) def send_to_strategies(self, cmd): self._lock.acquire() for (i,s) in enumerate(self.team1.strategies): if hasattr(s, "listen"): s.listen(cmd,1,i) for (i,s) in enumerate(self.team2.strategies): if hasattr(s, "listen"): s.listen(cmd,2,i) self._lock.release() def __str__(self): return self.to_str() def __repr__(self): return self.to_str() def copy(self): return deepcopy(self) def to_str(self): return "%s\n%s\n%s" % (str(self.team1), str(self.team2), "\n".join(str(s) for s in self._states)) @classmethod def from_str(cls, strg): l_tmp = strg.split("\n") res = cls(SoccerTeam.from_str(l_tmp[0]), SoccerTeam.from_str(l_tmp[1])) res._states = [SoccerState.from_str(x) for x in l_tmp[2:] if len(x) > 0] res._state = res._states[-1] res._replay = True return res