Esempio n. 1
0
def tournament_deserializer(reloaded_tournament):
    tournament = Tournament(reloaded_tournament["name"],
                            reloaded_tournament["place"],
                            reloaded_tournament["date"],
                            reloaded_tournament["time_control"],
                            reloaded_tournament["details"])
    tournament.status = reloaded_tournament["status"]
    tournament.players = list()
    tournament.rounds = list()

    for player in reloaded_tournament["players"]:
        player = player_deserializer(player)
        tournament.add_player(player)

    for round in reloaded_tournament["rounds"]:
        reload_round = round_deserializer(round)
        tournament.add_round(reload_round)

    return tournament
class TournamentControler:
    """ Classe qui lance et fait fonctionner le tournoi """
    def __init__(self):
        self.tournament_progress = ""

    def new_tournament_created(self, db):
        self.tournament_progress = Tournament(
            vt.get_tournament_name(),
            vt.get_tournament_place(),
            str(vt.get_tournament_date()),
            4,
            [],
            [],
            [],
            vt.get_tournament_time_control(),
            vt.get_tournament_description(),
        )

        tournament_table = db.table(f"{self.tournament_progress.name}")

        serialized_tournament = self.tournament_progress.serialize()
        tournament_table.insert(serialized_tournament)

        return tournament_table

    def init_players(self, tournament_table, actors_db):
        """ Fonction qui instancie les joueurs du tournoi """
        for i in range(8):
            input(f"\nEnter player{i+1} informations [ENTER]\n")
            name = vp.get_player_name()
            surname = vp.get_player_surname()
            birthday = vp.get_player_birthday()
            sexe = vp.get_player_sexe()
            elo = vp.get_player_elo()
            score = 0
            player = Player(name, surname, birthday, sexe, elo, score)
            self.tournament_progress.add_player(player)

            serialized_player = player.serialize()
            actor_table = actors_db.table(f"{name}")

            User = Query()
            actor_table.upsert(serialized_player, User.name == name)

            self.tournament_progress.serialized_players.append(
                serialized_player)

        self.tournament_progress.serialized_tournament = (
            self.tournament_progress.serialize())

        tournament_table.truncate()
        tournament_table.insert(self.tournament_progress.serialized_tournament)

    def print_all_players(self):
        """ Fonction qui imprime les joueurs d'un tournoi"""
        print(self.tournament_progress.players)

    def handle_score(self, match):
        """ Fonction qui calcule le score d'un match """
        score = vr.enter_score(match)
        while score != "1" and score != "2" and score != "3":
            score = vr.enter_score(match)

        if score == "1":
            return 1, 0
        elif score == "2":
            return 0, 1
        elif score == "3":
            return 0.5, 0.5

    def get_players(self):
        """ Fonction qui tri les players par elo et par score """
        players = []
        for player in self.tournament_progress.players:
            players.append(player)
        players.sort(key=lambda x: x.elo)
        players.sort(key=lambda x: x.score, reverse=True)

        return players

    def make_pairing(self, players, current_round):
        """ Algorithme qui crée les paires de match """
        i = 0
        while len(players) != 0:
            player1 = players[i]
            player1_index = i
            player2 = players[i + 1]
            player2_index = i + 1

            player2_id = player2.surname + player2.elo
            while player2_id in player1.opponents:
                try:
                    i += 1
                    player2 = players[i + 1]
                    player2_index = i + 1
                    player2_id = player2.surname + player2.elo

                except IndexError:
                    player2 = players[i]
                    player2_index = i
                    player2_id = player2.surname + player2
                    break

            current_round.add_match(player1, player2)

            del players[player2_index]
            del players[player1_index]

            i = 0

    def run_first_round(self, tournament_table, actors_db):
        """ Fonction qui fait tourner le premier round """
        round_name = "Round 1"
        round_date = str(vr.get_round_date())
        round_starttime = str(vr.get_round_starttime())
        round1 = Round(round_name, round_date, round_starttime)
        serialized_round1 = round1.serialize()

        self.tournament_progress.serialized_rounds.append(serialized_round1)
        self.tournament_progress.serialized_rounds = (
            self.tournament_progress.serialized_rounds)
        vt.print_info(
            f"{self.tournament_progress.name} begins !\n--------------------------------------\n"
        )
        vt.print_info(f"{round_name} launchment...")

        self.tournament_progress.players.sort(key=lambda x: x.elo)
        for i in range(4):
            round1.add_match(
                self.tournament_progress.players[i],
                self.tournament_progress.players[4 + i],
            )
        self.tournament_progress.add_round(round1)

        i = 0
        for match in self.tournament_progress.rounds[0].matchs:
            vt.print_info("\n...\n")
            vt.print_info(
                f"{match.player1.name} and {match.player2.name} play against each other !"
            )
            match.score1, match.score2 = self.handle_score(match)
            i += 1

            vr.print_match_result(match)

            serialized_match = match.serialize()
            round1.serialized_matchs.append(serialized_match)

            match.player1.add_opponent(match.player2)
            match.player2.add_opponent(match.player1)
            match.player1.add_score(match.score1)
            match.player2.add_score(match.score2)

            tournament_table.truncate()
            tournament_table.insert(
                self.tournament_progress.serialized_tournament)

        round1.endtime = str(vr.get_round_endtime())
        serialized_round1 = {
            "Round end-time": round1.endtime,
            "Round Matchs": round1.serialized_matchs,
        }
        self.tournament_progress.serialized_tournament = (
            self.tournament_progress.serialize())
        tournament_table.truncate()
        tournament_table.insert(self.tournament_progress.serialized_tournament)

        vt.print_info(f"End of the Round1 at {round1.endtime}.")
        vt.print_info("\n--------------------------------------\n")

    def run_rounds(self, tournament_table, actors_db, next_round_number=2):
        """ Fonction qui fait tourner les rounds suivants """
        for i in range(next_round_number, 5):
            players = self.get_players()
            round_name = f"Round {i}"
            round_date = vr.get_round_date()
            round_starttime = vr.get_round_starttime()
            round_endtime = " "
            next_round = Round(round_name, round_date, round_starttime,
                               round_endtime)
            self.tournament_progress.add_round(next_round)

            serialized_next_round = next_round.serialize()

            self.tournament_progress.serialized_rounds.append(
                serialized_next_round)
            self.tournament_progress.serialized_rounds = (
                self.tournament_progress.serialized_rounds)
            self.serialized_tournament = self.tournament_progress.serialize()

            vt.print_info(f"{round_name} launchment...")

            self.make_pairing(players, next_round)
            self.tournament_progress.serialized_players.clear()

            for match in self.tournament_progress.rounds[i - 1].matchs:
                vt.print_info("\n...\n")
                vt.print_info(
                    f"{match.player1.name} and {match.player2.name} play against each other !"
                )

                match.score1, match.score2 = self.handle_score(match)
                vr.print_match_result(match)

                serialized_match = match.serialize()
                next_round.serialized_matchs.append(serialized_match)

                match.player1.add_opponent(match.player2)
                match.player2.add_opponent(match.player1)
                match.player1.add_score(match.score1)
                match.player2.add_score(match.score2)

                serialized_player1 = match.player1.serialize()
                self.tournament_progress.serialized_players.append(
                    serialized_player1)

                serialized_player2 = match.player2.serialize()
                self.tournament_progress.serialized_players.append(
                    serialized_player2)

                self.tournament_progress.serialized_tournament = (
                    self.tournament_progress.serialize())
                tournament_table.update(
                    self.tournament_progress.serialized_tournament)

            next_round.endtime = vr.get_round_endtime()
            endtime = next_round.serialize_endtime()

            tournament_table.update(
                self.tournament_progress.serialized_tournament)
            vt.print_info(f"End of the {round_name} at {next_round.endtime}.")
            vt.print_info("\n--------------------------------------\n")
            i += 1

        self.tournament_progress.serialized_tournament = (
            self.tournament_progress.serialize())
        vt.print_info(
            f"{self.tournament_progress.name} is over !\n--------------------------------------\n"
        )
        vt.print_players_scores(self.tournament_progress.players)
        return tournament_table, actors_db

    def run_ungoing_tournament(self, db, tournament_name, actors_db):
        """ Fonction qui reprends un tournoi existant non terminé """
        tournament_table = db.table(f"{tournament_name}")

        self.instanciation_tournament(tournament_table, tournament_name)
        self.instanciation_players()
        self.instanciation_rounds()

        last_round_index = 0

        for i in range(len(self.tournament_progress.rounds) - 1):
            self.instanciation_matchs(i)
            last_round_index += 1

        r = len(self.tournament_progress.rounds)
        m = len(self.tournament_progress.rounds[last_round_index].matchs)

        if r == 0 and m < 3:
            self.run_first_round(tournament_table, actors_db)
        elif r == 1 and m < 3:
            self.run_rounds(tournament_table, actors_db, next_round_number=2)
        elif r == 2 and m < 3:
            self.run_rounds(tournament_table, actors_db, next_round_number=3)
        elif r == 3 and m < 3:
            self.run_rounds(tournament_table, actors_db, next_round_number=4)

    def instanciation_tournament(self, tournament_table, tournament_name):
        """ Fonction qui instancie le tournoi à partir du .json """
        liste_tournament = tournament_table.search(
            where("Name") == tournament_name)
        data = liste_tournament[0]

        self.tournament_progress = Tournament(
            data["Name"],
            data["Place"],
            data["Date"],
            data["Numbers of rounds"],
            data["Rounds"],
            [],
            data["Players"],
            data["Type"],
            data["Description"],
        )

    def instanciation_players(self):
        """ Fonction qui instancie les joueurs du tournoi à partir du .json """
        for serialized_player in self.tournament_progress.serialized_players:

            p = Player(
                serialized_player["Name"],
                serialized_player["Surname"],
                serialized_player["Birthday"],
                serialized_player["Sexe"],
                serialized_player["ELO"],
            )
            self.tournament_progress.add_player(p)

    def instanciation_rounds(self):
        """ Fonction qui instancie les rounds du tournoi à partir du .json """
        for serialized_round in self.tournament_progress.serialized_rounds:

            r = Round(
                serialized_round["Name"],
                serialized_round["Date"],
                serialized_round["Round start-time"],
                [],
            )

            self.tournament_progress.add_round(r)

    def instanciation_matchs(self, i):
        """ Fonction qui instancie les matchs du tournoi à partir du .json """
        round_table = self.tournament_progress.serialized_rounds[i]
        round_matchs = round_table["Round Matchs"]

        for s_match in round_matchs:
            print(s_match)
            m = Match(
                player1=s_match["Player1"],
                player2=s_match["Player2"],
                score1=s_match["Score1"],
                score2=s_match["Score2"],
            )

            self.tournament_progress.rounds[i].add_match(m.player1, m.player2)

    def run_new_tournament(self, db, actors_db):
        """ Fonction qui lance un nouveau tournoi """
        tournament_table = self.new_tournament_created(db)

        self.init_players(tournament_table, actors_db)
        self.run_first_round(tournament_table, actors_db)
        self.run_rounds(tournament_table, actors_db)
class TournamentController:
    def __init__(self):
        self.tournament = None
        self.db = TinyDB("tournament_data.json", indent=4)
        self.tournament_data = self.db.table("tournament_data")

    def new_tournament(self):
        tournaments = Query()
        name = self.get_and_check_name()
        place = self.get_and_check_place()
        date = set_date()
        time_control = self.get_and_check_time_control()
        details = get_tournament_details()
        self.tournament = Tournament(name, place, date, time_control, details)
        self.tournament.status = "En cours"
        self.tournament.players = list()
        self.tournament_data.insert(tournament_serializer(self.tournament))
        tournament_get = self.tournament_data.get(
            (tournaments.name == self.tournament.name)
            & (tournaments.place == self.tournament.place))
        tournament_id = tournament_get.doc_id
        for i in range(1, 9):
            playerController = PlayerController()
            print_text(f"Joueur {i} : ")
            player = playerController.handle_players_choice()
            self.tournament.add_player(player)
            self.tournament_data.update(tournament_serializer(self.tournament),
                                        doc_ids=[tournament_id])
        self.run_first_round()
        self.tournament_data.update(tournament_serializer(self.tournament),
                                    doc_ids=[tournament_id])
        quit = self.get_and_check_continue_or_quit()
        if quit == "q":
            return
        else:
            pass
        for round_number in range(2, 5):
            self.run_round(round_number)
            self.tournament_data.update(tournament_serializer(self.tournament),
                                        doc_ids=[tournament_id])
            quit = self.get_and_check_continue_or_quit()
            if quit == "q":
                return
            else:
                pass
        self.tournament.status = "Terminé"
        self.tournament_data.update(tournament_serializer(self.tournament),
                                    doc_ids=[tournament_id])

        update_elo = self.check_update_player_elo()

        while True:
            if update_elo == "o":
                PlayerController.update_player_elo()
                update_elo = self.check_update_player_elo()
            else:
                return

    def reload_tournament(self):
        self.db = TinyDB("tournament_data.json", indent=4)
        tournaments = Query()
        self.tournament_data = self.db.table("tournament_data")

        db_tournament = self.tournament_data.search(
            tournaments.status == "En cours")

        while is_query_empty(db_tournament):
            error_message("Aucun tournoi en cours")
            return

        print_current_tournaments()

        for db_tour in db_tournament:
            number_round_to_run = 4 - len(db_tour["rounds"])
            print_existing_tournaments(db_tour)
            print_number_round_to_run(number_round_to_run)

        choice = tournament_choice()

        reloaded_tournament = self.tournament_data.get(doc_id=choice)

        self.tournament = None
        self.tournament = tournament_deserializer(reloaded_tournament)
        self.tournament.date = set_date()

        nb_of_players = len(self.tournament.players)

        if nb_of_players < 8:
            for i in range(1, (9 - nb_of_players)):
                playerController = PlayerController()
                print_text(f"Joueur {i + nb_of_players} : ")
                player = playerController.handle_players_choice()
                self.tournament.add_player(player)
                self.tournament_data.update(tournament_serializer(
                    self.tournament),
                                            doc_ids=[choice])

        number_round_to_run = 4 - len(self.tournament.rounds)

        if number_round_to_run == 4:
            self.run_first_round()
            self.tournament_data.update(tournament_serializer(self.tournament),
                                        doc_ids=[choice])
            quit = self.get_and_check_continue_or_quit()
            if quit == "q":
                return
            else:
                pass
            for i in range(2, 5):
                self.run_round(i)
                self.tournament_data.update(tournament_serializer(
                    self.tournament),
                                            doc_ids=[choice])
                quit = self.get_and_check_continue_or_quit()
                if quit == "q":
                    return
                else:
                    pass
        else:
            for i in range(len(self.tournament.rounds) + 1, 5):
                self.run_round(i)
                self.tournament_data.update(tournament_serializer(
                    self.tournament),
                                            doc_ids=[choice])
                quit = self.get_and_check_continue_or_quit()
                if quit == "q":
                    return
                else:
                    pass
        self.tournament.status = "Terminé"
        self.tournament_data.update(tournament_serializer(self.tournament),
                                    doc_ids=[choice])

        update_elo = self.check_update_player_elo()

        while True:
            if update_elo == "o":
                PlayerController.update_player_elo()
                update_elo = self.check_update_player_elo()
            else:
                return

    def run_first_round(self):
        # algorithme pour créer les premiers rounds

        match_number = 1

        start_time = set_round_time()
        end_time = None
        round1 = Round("1", start_time, end_time)
        self.tournament.add_round(round1)

        player_for_round = self.get_players()
        print_player(player_for_round)

        for i in range(4):
            round1.add_match(player_for_round[i], player_for_round[i + 4])

        for match in round1.matches:
            match.player1.opponent.append(match.player2.elo)
            match.player2.opponent.append(match.player1.elo)

        for match in self.tournament.rounds[0].matches:
            print_text(f"\nROUND #1 - MATCH #{match_number}")
            print_match(match)
            match.score_player1, match.score_player2 = self.handle_score()
            print_text(f"\nRÉSULTAT DU MATCH #{match_number}")
            match_number += 1
            print_match_result(match)
            self.update_tournament_score(match)
        self.tournament.players.sort(key=lambda x: x.elo, reverse=True)
        self.tournament.players.sort(key=lambda x: x.score, reverse=True)
        print_final_score(self.tournament.players, round1.round_number)
        round1.end_time = set_round_time()

    def run_round(self, round_number):
        match_number = 1

        start_time = set_round_time()
        end_time = None
        round = Round(str(round_number), start_time, end_time)
        self.tournament.add_round(round)

        player_for_round = self.get_players()
        print_player(player_for_round)

        index_player = 0

        while len(player_for_round) != 0:
            player1 = player_for_round[index_player]
            player1_index = index_player
            player2 = player_for_round[index_player + 1]
            player2_index = index_player + 1

            while player2.elo in player1.opponent:
                index_player += 1
                player2 = player_for_round[index_player + 1]
                player2_index = index_player + 1
            round.add_match(player1, player2)
            del player_for_round[player1_index]
            del player_for_round[player2_index - 1]
            index_player = 0

        for match in round.matches:
            match.player1.opponent.append(match.player2.elo)
            match.player2.opponent.append(match.player1.elo)

        for i in range(1, 2):
            for match in self.tournament.rounds[round_number - 1].matches:
                print_text(f"\nROUND #{round_number} - MATCH #{match_number}")
                print_match(match)
                match.score_player1, match.score_player2 = self.handle_score()
                print_text(f"\nRÉSULTAT DU MATCH #{match_number}")
                match_number += 1
                print_match_result(match)
                self.update_tournament_score(match)
        self.tournament.players.sort(key=lambda x: x.elo, reverse=True)
        self.tournament.players.sort(key=lambda x: x.score, reverse=True)
        print_final_score(self.tournament.players, round.round_number)
        round.end_time = set_round_time()

    def get_players(self):
        player_for_round = list()
        for player in self.tournament.players:
            player_for_round.append(player)
        player_for_round.sort(key=lambda x: x.elo, reverse=True)
        player_for_round.sort(key=lambda x: x.score, reverse=True)
        return player_for_round

    def handle_score(self):
        score = enter_score()
        if (score == "1"):
            return 1, 0
        elif (score == "2"):
            return 0, 1
        else:
            return 0.5, 0.5

    def get_and_check_name(self):
        name = get_tournament_name()
        name = name.strip().capitalize()
        while not is_tournament_name_valid(name):
            error_message("Le format du nom est incorrect")
            name = get_tournament_name()
            name = name.strip().capitalize()
        return name

    def get_and_check_place(self):
        place = get_tournament_place()
        place = place.strip().capitalize()
        while not is_place_valid(place):
            error_message("Le format du lieu est incorrect")
            place = get_tournament_place()
            place = place.strip().capitalize()
        return place

    def get_and_check_time_control(self):
        time_control = get_tournament_time_control()
        time_control = time_control.lower()
        while is_time_control_valid(time_control):
            error_message("Le format du contrôle du temps est incorrect")
            time_control = get_tournament_time_control()
            time_control = time_control.lower()
        else:
            time_control = time_control_def(time_control)
        return time_control

    def get_and_check_continue_or_quit(self):
        quit = get_continue_or_quit()
        quit = quit.lower()

        while not is_continue_or_quit(quit):
            error_message("Aucune commande correspondante")
            quit = get_continue_or_quit()
            quit = quit.lower()
        return quit

    def update_tournament_score(self, match):
        match.player1.score += match.score_player1
        match.player2.score += match.score_player2

    def check_update_player_elo(self):
        update_elo = print_update_player_elo()
        update_elo = update_elo.lower()

        while not is_update_player_elo_valid(update_elo):
            error_message("Entrez uniquement " "O" " ou " "N" "")
            update_elo = print_update_player_elo()
            update_elo = update_elo.lower()
        return update_elo