예제 #1
0
def import_results(args):
    """
    Imports the match data of a csv file into the result table.

    :param args: A list with arguments from the argument parser
    :type args: namespace
    """

    print "Importing results from", args.file

    try:
        csvfile, reader, hasHeader = utils.get_csv(args.file)
        line = 0

        if hasHeader:
            print "\tFirst line of csv file is ignored. It seems to be a " \
                  "header row.\n"

        # nickname --> player
        players = {}

        for row in reader:
            if line != 0 or (line == 0 and not hasHeader):
                if row[1] is row[2]:
                    continue

                player1 = players.get(row[1], None)
                player2 = players.get(row[2], None)
                if player1 is None:
                    player1, created = utils.add_player(row[1], commit=False)
                    players[player1.nickname.value] = player1
                if player2 is None:
                    player2, created = utils.add_player(row[2], commit=False)
                    players[player2.nickname.value] = player2

                dbRow = Match1on1(player1=player1.player_id.value,
                                  player2=player2.player_id.value,
                                  outcome=row[3],
                                  date=row[0])
                dbRow.save(commit=False)

            if line % 100 == 0:
                sys.stdout.write("\r" + "Imported %d entries..." % line)
                sys.stdout.flush()
            line = line + 1

        Rank_Elo.commit()
        Rank_Glicko.commit()
        Match1on1.commit()
        csvfile.close()
        print "\rImported %d entries." % (line - (1 if hasHeader else 0))
    except csv.Error:
        print "Error importing %s in line %d" % (args.file, line)
    except IOError:
        print "No such file: %s" % args.file
예제 #2
0
def import_results(args):
    """
    Imports the match data of a csv file into the result table.

    :param args: A list with arguments from the argument parser
    :type args: namespace
    """

    print "Importing results from", args.file

    try:
        csvfile, reader, hasHeader = utils.get_csv(args.file)
        line = 0

        if hasHeader:
            print "\tFirst line of csv file is ignored. It seems to be a " \
                  "header row.\n"

        # nickname --> player
        players = {}

        for row in reader:
            if line != 0 or (line == 0 and not hasHeader):
                if row[1] is row[2]:
                    continue

                player1 = players.get(row[1], None)
                player2 = players.get(row[2], None)
                if player1 is None:
                    player1, created = utils.add_player(row[1], commit=False)
                    players[player1.nickname.value] = player1
                if player2 is None:
                    player2, created = utils.add_player(row[2], commit=False)
                    players[player2.nickname.value] = player2

                dbRow = Match1on1(player1=player1.player_id.value,
                    player2=player2.player_id.value, outcome=row[3],
                    date=row[0])
                dbRow.save(commit=False)

            if line % 100 == 0:
                sys.stdout.write("\r" + "Imported %d entries..." % line)
                sys.stdout.flush()
            line = line + 1

        Rank_Elo.commit()
        Rank_Glicko.commit()
        Match1on1.commit()
        csvfile.close()
        print "\rImported %d entries." % (line - (1 if hasHeader else 0))
    except csv.Error:
        print "Error importing %s in line %d" % (args.file, line)
    except IOError:
        print "No such file: %s" % args.file
예제 #3
0
def add_result(args):
    """
    Adds a result row to the result table.

    :param args: A list with arguments from the argument parser
    :type args: namespace
    """
    if args.player1 is args.player2:
        print "A player can not play against himself."
        return
    print "Adding a result for %s" % args.game
    print "\tPlayer 1:", args.player1
    print "\tPlayer 2:", args.player2
    print "\tOutcome: ", utils.outcomes[args.outcome]
    print "\tDate: ", args.date

    player1 = utils.add_player(args.player1, commit=False)
    player2 = utils.add_player(args.player2, commit=False)

    pid1 = player1.player_id.value
    pid2 = player2.player_id.value

    dbRow = Match1on1(player1=pid1,
                      player2=pid2,
                      outcome=args.outcome,
                      date=args.date)
    dbRow.save(commit=True)

    print "Done"
예제 #4
0
def clear(args):
    def clear_elo():
        ranks = Rank_Elo.query().all()
        for rank in ranks:
            rank.value = 1500
            rank.save(commit=False)
        Rank_Elo.commit()

    def clear_glicko():
        ranks = Rank_Glicko.query().all()
        for rank in ranks:
            rank.rd = 350
            rank.rating = 350
            rank.last_match = 0
            rank.save(commit=False)
        Rank_Glicko.commit()

    """
    Clears ranks or matches or both.
    """

    if not args.ranks and not args.matches:
        print "You have to specify either --ranks or --matches, or both."
        return

    # (ranks, matches) --> output string
    output = {
        (True, True): 'ranks and matches',
        (True, False): 'ranks',
        (False, True): 'matches',
        (False, False): ''
    }
    print "Clearing %s..." % output[args.ranks, args.matches]

    # clear ranks
    if args.ranks:
        clear_funcs = {'elo': clear_elo, 'glicko': clear_glicko}
        clear_funcs[args.algorithm]()

    # clear matches
    if args.matches:
        Match1on1.query().truncate()
예제 #5
0
def clear(args):
    def clear_elo():
        ranks = Rank_Elo.query().all()
        for rank in ranks:
            rank.value = 1500
            rank.save(commit=False)
        Rank_Elo.commit()

    def clear_glicko():
        ranks = Rank_Glicko.query().all()
        for rank in ranks:
            rank.rd = 350
            rank.rating = 350
            rank.last_match = 0
            rank.save(commit=False)
        Rank_Glicko.commit()

    """
    Clears ranks or matches or both.
    """

    if not args.ranks and not args.matches:
        print "You have to specify either --ranks or --matches, or both."
        return

    # (ranks, matches) --> output string
    output = {(True, True): 'ranks and matches', (True, False): 'ranks',
        (False, True): 'matches', (False, False): ''}
    print "Clearing %s..." % output[args.ranks, args.matches]

    # clear ranks
    if args.ranks:
        clear_funcs = {'elo': clear_elo, 'glicko': clear_glicko}
        clear_funcs[args.algorithm]()

    # clear matches
    if args.matches:
        Match1on1.query().truncate()
예제 #6
0
    def update_elo():
        sys.stdout.write("Query matches...")
        matches = Match1on1.query().all()
        sys.stdout.write("\rBeginning to update %d matches" % len(matches))
        print ""

        # constants
        conf = utils.get_config(args)
        k = conf["elo.chess.k"]
        func = conf["elo.chess.function"]

        # Query all ratings and store it in a dictionary. This is done to store
        # the newest rating data in memory. We do not have to commit.
        ratings = Rank_Elo.query().all()
        rdict = {}
        for r in ratings:
            rdict[r.player_id.value] = r

        updates = 0
        for match in matches:
            rating1 = rdict[match.player1.value]
            rating2 = rdict[match.player2.value]

            result = elo.elo1on1(rating1.value.value, rating2.value.value,
                                 match.outcome.value, k, func)
            rating1.value = result[0]
            rating2.value = result[1]

            updates = updates + 1
            if updates % 50 == 0:
                sys.stdout.write("\r" + "Updated %d matches..." % updates)
                sys.stdout.flush()

        # update table
        for r in ratings:
            r.save(commit=False)
        Rank_Elo.commit()
        print "\rUpdated", updates, "matches."
예제 #7
0
    def update_elo():
        sys.stdout.write("Query matches...")
        matches = Match1on1.query().all()
        sys.stdout.write("\rBeginning to update %d matches" % len(matches))
        print ""

        # constants
        conf = utils.get_config(args)
        k = conf["elo.chess.k"]
        func = conf["elo.chess.function"]

        # Query all ratings and store it in a dictionary. This is done to store
        # the newest rating data in memory. We do not have to commit.
        ratings = Rank_Elo.query().all()
        rdict = {}
        for r in ratings:
            rdict[r.player_id.value] = r

        updates = 0
        for match in matches:
            rating1 = rdict[match.player1.value]
            rating2 = rdict[match.player2.value]

            result = elo.elo1on1(rating1.value.value, rating2.value.value,
                match.outcome.value, k, func)
            rating1.value = result[0]
            rating2.value = result[1]

            updates = updates + 1
            if updates % 50 == 0:
                sys.stdout.write("\r" + "Updated %d matches..." % updates)
                sys.stdout.flush()

        # update table
        for r in ratings:
            r.save(commit=False)
        Rank_Elo.commit()
        print "\rUpdated", updates, "matches."
예제 #8
0
def history(args):

    if args.player1 == args.player2:
        print "Player1 and Player2 are equal. Use 'history <player>'."
        return

    # store all players in a dict (player_id --> player) and get player1/2
    players = Player.query().all()
    pdict = {}
    for player in players:
        pdict[player.player_id.value] = player
        if player.nickname.value == args.player1:
            player1 = player
        if player.nickname.value == args.player2:
            player2 = player

    if args.player2 is None:
        print "Searching for the history of %s\n" % args.player1

        # the table to print out
        table = [['Opponent', 'Outcome', 'Date']]

        # get all matches with player 1
        matches = Match1on1.query().filter(
            player1=player1.player_id.value).filter(
                player2=player1.player_id.value).join_or().all()

        won = 0
        lost = 0
        draw = 0

        # iterate over all matches
        for match in matches:
            # check who the opponent is and who actually won
            opponent = match.player1.value
            if match.outcome.value == 0.5:
                outcome = "Draw"
                draw += 1
            if opponent == player1.player_id.value:
                opponent = match.player2.value
                if match.outcome.value == 1:
                    outcome = "Won"
                    won += 1
                elif match.outcome.value == 0:
                    lost += 1
                    outcome = "Lost"
            else:
                if match.outcome.value == 1:
                    outcome = "Lost"
                    lost += 1
                elif match.outcome.value == 0:
                    outcome = "Won"
                    won += 1

            table.append(
                [pdict[opponent].nickname.value, outcome, match.date.value])

        # finally print the table
        utils.print_table(table)
        print "\nStatistics:"
        print "Won:  %d\nLost: %d\nDraw: %d" % (won, lost, draw)

    else:
        #TODO modify this when IN (...) works
        print "Searching for the history of %s and %s\n" % (args.player1,
                                                            args.player2)

        # the table to print out
        table = [['Winner', 'Date']]

        # get all matches with player 1
        matches1 = Match1on1.query().filter(
            player1=player1.player_id.value).filter(
                player2=player1.player_id.value).join_or().all()

        # get all matches with player 2
        matches2 = Match1on1.query().filter(
            player1=player2.player_id.value).filter(
                player2=player2.player_id.value).join_or().all()

        statistics = {args.player1: 0, args.player2: 0, 'Draw': 0}

        # Find the intersection of the two list. Other methods do not work
        # because the 'in' operator does not seem to work with instances
        matches = [
            x for x in matches1
            if [y for y in matches2 if y.match_id.value == x.match_id.value]
        ]

        for match in matches:
            if match.outcome.value == 0:
                nickname = pdict[match.player2.value].nickname.value
                table.append([nickname, match.date.value])
                statistics[nickname] += 1
            elif match.outcome.value == 1:
                nickname = pdict[match.player2.value].nickname.value
                table.append([nickname, match.date.value])
                statistics[nickname] += 1
            else:
                table.append(['Draw', match.date.value])
                statistics['Draw'] += 1

        # finally print the table
        utils.print_table(table)

        print "\nStatistics for %s:" % args.player1
        print "Won:  %d\nLost: %d\nDraw: %d" % (
            statistics[args.player1], len(matches) - statistics[args.player1] -
            statistics["Draw"], statistics["Draw"])

        print "\nStatistics for %s:" % args.player2
        print "Won:  %d\nLost: %d\nDraw: %d" % (
            statistics[args.player2], len(matches) - statistics[args.player2] -
            statistics["Draw"], statistics["Draw"])
예제 #9
0
    def update_glicko():
        sys.stdout.write("Query matches...")
        matches = Match1on1.query().all()
        sys.stdout.write("\rBeginning to update %d matches" % len(matches))
        print ""

        # Query all ratings and store it in a dictionary. This is done to store
        # the newest rating data in memory. We do not have to commit.
        ratings = Rank_Glicko.query().all()
        rdict = {}
        for r in ratings:
            rdict[r.player_id.value] = r

        # sort matches by date
        matches = sorted(matches, key=lambda x: x.date.value)
        mDict = {}

        for match in matches:
            if match.date.value in mDict:
                mDict[match.date.value].append(match)
            else:
                mDict[match.date.value] = [match]

        # for each rating period...
        for period, pMatches in mDict.iteritems():
            # players in current period --> (RD, rating)
            pDict = {}
            for match in pMatches:
                for player in [match.player1.value, match.player2.value]:
                    if player not in pDict:
                        pDict[player] = (rdict[player].rd.value,
                                         rdict[player].rating.value)
                        # glicko.chess.c
                        curRD = glicko.getCurrentRD(
                            pDict[player][0], 15.8,
                            period - rdict[player].last_match.value)
                        curRating = rdict[player].rating.value
                        # search all matches the player participated, in period
                        ratingList = []
                        RDList = []
                        outcomeList = []
                        for m in pMatches:
                            # player is player1 of match
                            if m.player1.value == player:
                                if m.player2.value in pDict:
                                    ratingList.append(
                                        pDict[m.player2.value][1])
                                    RDList.append(pDict[m.player2.value][0])
                                else:
                                    ratingList.append(
                                        rdict[m.player2.value].rating.value)
                                    RDList.append(
                                        rdict[m.player2.value].rd.value)
                                outcomeList.append(m.outcome.value)
                            # player player2 of match
                            if m.player2.value == player:
                                if m.player1.value in pDict:
                                    ratingList.append(
                                        pDict[m.player1.value][1])
                                    RDList.append(pDict[m.player1.value][0])
                                else:
                                    ratingList.append(
                                        rdict[m.player1.value].rating.value)
                                    RDList.append(
                                        rdict[m.player1.value].rd.value)
                                outcomeList.append(1.0 - m.outcome.value)

                        # calculate new rating
                        newRating = glicko.newRating(curRD, curRating,
                                                     ratingList, RDList,
                                                     outcomeList)
                        newRD = glicko.newRD(curRD, newRating, ratingList,
                                             RDList)

                        rdict[player].rd.value = newRD
                        rdict[player].rating.value = newRating
                        rdict[player].last_match.value = period
                        rdict[player].save(commit=False)

            Rank_Glicko.commit()
            stage = period % 4
            if stage == 0:
                sys.stdout.write("\r| ")
            elif stage == 1:
                sys.stdout.write("\r/ ")
            elif stage == 2:
                sys.stdout.write("\r--")
            else:
                sys.stdout.write("\r\\ ")
            sys.stdout.flush()
        print "\rDone."
예제 #10
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pychallenge.models import Config, Match1on1, Player, Rank_Elo, Rank_Glicko

if __name__ == "__main__":
    Config.create()
    Match1on1.create()
    Player.create()
    Rank_Elo.create()
    Rank_Glicko.create()
예제 #11
0
def history(args):

    if args.player1 == args.player2:
        print "Player1 and Player2 are equal. Use 'history <player>'."
        return

    # store all players in a dict (player_id --> player) and get player1/2
    players = Player.query().all()
    pdict = {}
    for player in players:
        pdict[player.player_id.value] = player
        if player.nickname.value == args.player1:
            player1 = player
        if player.nickname.value == args.player2:
            player2 = player

    if args.player2 is None:
        print "Searching for the history of %s\n" % args.player1

        # the table to print out
        table = [['Opponent', 'Outcome', 'Date']]

        # get all matches with player 1
        matches = Match1on1.query().filter(
            player1=player1.player_id.value).filter(
            player2=player1.player_id.value).join_or().all()

        won = 0
        lost = 0
        draw = 0

        # iterate over all matches
        for match in matches:
            # check who the opponent is and who actually won
            opponent = match.player1.value
            if match.outcome.value == 0.5:
                outcome = "Draw"
                draw += 1
            if opponent == player1.player_id.value:
                opponent = match.player2.value
                if match.outcome.value == 1:
                    outcome = "Won"
                    won += 1
                elif match.outcome.value == 0:
                    lost += 1
                    outcome = "Lost"
            else:
                if match.outcome.value == 1:
                    outcome = "Lost"
                    lost += 1
                elif match.outcome.value == 0:
                    outcome = "Won"
                    won += 1

            table.append([pdict[opponent].nickname.value, outcome,
                match.date.value])

        # finally print the table
        utils.print_table(table)
        print "\nStatistics:"
        print "Won:  %d\nLost: %d\nDraw: %d" % (won, lost, draw)

    else:
        #TODO modify this when IN (...) works
        print "Searching for the history of %s and %s\n" % (args.player1,
            args.player2)

        # the table to print out
        table = [['Winner', 'Date']]

        # get all matches with player 1
        matches1 = Match1on1.query().filter(
            player1=player1.player_id.value).filter(
            player2=player1.player_id.value).join_or().all()

        # get all matches with player 2
        matches2 = Match1on1.query().filter(
            player1=player2.player_id.value).filter(
            player2=player2.player_id.value).join_or().all()

        statistics = {args.player1: 0, args.player2: 0, 'Draw': 0}

        # Find the intersection of the two list. Other methods do not work
        # because the 'in' operator does not seem to work with instances
        matches = [x for x in matches1 if
            [y for y in matches2 if y.match_id.value == x.match_id.value]]

        for match in matches:
            if match.outcome.value == 0:
                nickname = pdict[match.player2.value].nickname.value
                table.append([nickname, match.date.value])
                statistics[nickname] += 1
            elif match.outcome.value == 1:
                nickname = pdict[match.player2.value].nickname.value
                table.append([nickname, match.date.value])
                statistics[nickname] += 1
            else:
                table.append(['Draw', match.date.value])
                statistics['Draw'] += 1

        # finally print the table
        utils.print_table(table)

        print "\nStatistics for %s:" % args.player1
        print "Won:  %d\nLost: %d\nDraw: %d" % (statistics[args.player1],
            len(matches) - statistics[args.player1] - statistics["Draw"],
            statistics["Draw"])

        print "\nStatistics for %s:" % args.player2
        print "Won:  %d\nLost: %d\nDraw: %d" % (statistics[args.player2],
            len(matches) - statistics[args.player2] - statistics["Draw"],
            statistics["Draw"])
예제 #12
0
    def update_glicko():
        sys.stdout.write("Query matches...")
        matches = Match1on1.query().all()
        sys.stdout.write("\rBeginning to update %d matches" % len(matches))
        print ""

        # Query all ratings and store it in a dictionary. This is done to store
        # the newest rating data in memory. We do not have to commit.
        ratings = Rank_Glicko.query().all()
        rdict = {}
        for r in ratings:
            rdict[r.player_id.value] = r

        # sort matches by date
        matches = sorted(matches, key=lambda x: x.date.value)
        mDict = {}

        for match in matches:
            if match.date.value in mDict:
                mDict[match.date.value].append(match)
            else:
                mDict[match.date.value] = [match]

        # for each rating period...
        for period, pMatches in mDict.iteritems():
            # players in current period --> (RD, rating)
            pDict = {}
            for match in pMatches:
                for player in [match.player1.value, match.player2.value]:
                    if player not in pDict:
                        pDict[player] = (rdict[player].rd.value,
                            rdict[player].rating.value)
                        # glicko.chess.c
                        curRD = glicko.getCurrentRD(pDict[player][0], 15.8,
                            period - rdict[player].last_match.value)
                        curRating = rdict[player].rating.value
                        # search all matches the player participated, in period
                        ratingList = []
                        RDList = []
                        outcomeList = []
                        for m in pMatches:
                            # player is player1 of match
                            if m.player1.value == player:
                                if m.player2.value in pDict:
                                    ratingList.append(
                                        pDict[m.player2.value][1])
                                    RDList.append(pDict[m.player2.value][0])
                                else:
                                    ratingList.append(
                                        rdict[m.player2.value].rating.value)
                                    RDList.append(
                                        rdict[m.player2.value].rd.value)
                                outcomeList.append(m.outcome.value)
                            # player player2 of match
                            if m.player2.value == player:
                                if m.player1.value in pDict:
                                    ratingList.append(
                                        pDict[m.player1.value][1])
                                    RDList.append(pDict[m.player1.value][0])
                                else:
                                    ratingList.append(
                                        rdict[m.player1.value].rating.value)
                                    RDList.append(
                                        rdict[m.player1.value].rd.value)
                                outcomeList.append(1.0 - m.outcome.value)

                        # calculate new rating
                        newRating = glicko.newRating(curRD, curRating,
                            ratingList, RDList, outcomeList)
                        newRD = glicko.newRD(curRD, newRating, ratingList,
                            RDList)

                        rdict[player].rd.value = newRD
                        rdict[player].rating.value = newRating
                        rdict[player].last_match.value = period
                        rdict[player].save(commit=False)

            Rank_Glicko.commit()
            stage = period % 4
            if stage == 0:
                sys.stdout.write("\r| ")
            elif stage == 1:
                sys.stdout.write("\r/ ")
            elif stage == 2:
                sys.stdout.write("\r--")
            else:
                sys.stdout.write("\r\\ ")
            sys.stdout.flush()
        print "\rDone."