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
示例#2
0
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()
示例#4
0
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