示例#1
0
def add_player(nickname, firstname="", lastname="", commit=False):
    """
    Adds a player and the corresponding ranks to the database. If the player
    already exsits, this function does nothing.

    :param nickname: The nickname of the player to add
    :type nickname: string
    :param firstname: The first name of the player to add
    :type firstname: string
    :param lastname: The last name of the player to add
    :type lastname: string
    :param commit: True if the rows should be committed
    :type commit: bool
    :return: Tupel (the player model, False if player already existed)
    """
    player = Player.query().get(nickname=nickname)
    created = False
    if player == None:
        created = True
        player = Player(firstname=firstname, lastname=lastname,
            nickname=nickname)
        player.save(commit)
        rank = Rank_Elo(player_id=player.player_id.value)
        rank.save(commit)
        rank = Rank_Glicko(player_id=player.player_id.value)
        rank.save(commit)

    return player, created
示例#2
0
def get_rating(args, p1=None, p2=None):
    def rating_elo(player):
        if player is None:
            return None
        return Rank_Elo.query().get(player_id=player.player_id.value)

    def rating_glicko(player):
        if player is None:
            return None
        return Rank_Glicko.query().get(player_id=player.player_id.value)

    def rating_glicko2():
        return None

    """
    Queries the rating of a given player or two given players. Returns one
    rank table, if "args.player" is defined. Returns a tupel of two rank
    tables, if "args.player1" and "args.player2" is defined.

    :param args: A list with arguments from the argument parser
    :type args: namespace
    :param p1: The nickname of a player
    :param p2: The nickname of another player
    :return: The rank for the given player(s) (either in args or in p1/p2)
    """

    rating_funcs = {
        'elo': rating_elo,
        'glicko': rating_glicko,
        'glicko2': rating_glicko2}

    if p1 is not None and p2 is not None:
        player1 = Player.query().get(nickname=p1)
        player2 = Player.query().get(nickname=p2)
        return (rating_funcs[args.algorithm](player1),
            rating_funcs[args.algorithm](player2))
    elif args.__dict__.get("player", None):
        player = Player.query().get(nickname=args.player)
        if player is None:
            return None
        return rating_funcs[args.algorithm](player)
    elif args.__dict__.get("player1", None) and args.__dict__.get("player2",
                                                                  None):
        player1 = Player.query().get(nickname=args.player1)
        player2 = Player.query().get(nickname=args.player2)
        return (rating_funcs[args.algorithm](player1),
            rating_funcs[args.algorithm](player2))

    return None
示例#3
0
def match(args):
    def match_elo(rating):
        ratings = Rank_Elo.query().all()
        best = None
        deviation = 99999999
        for r in ratings:
            if (best is None or abs(r.value.value - rating.value.value) <
                    deviation) and r.player_id.value != rating.player_id.value:
                best = r
                deviation = abs(r.value.value - rating.value.value)
        return best

    def match_glicko(rating):
        print "Not implemented yet"
        return None

    """
    Finds the best opponent for a given player.

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

    match_funcs = {'elo': match_elo, 'glicko': match_glicko}

    rating = utils.get_rating(args)
    if rating is None:
        print "Player %s is not known." % args.player
        return

    print "Looking for the best opponent for player %s..." % args.player

    opponent = match_funcs[args.algorithm](rating)

    if opponent is None:
        print "No opponent found."
        return

    print "Best opponent for player %s with rating %d is:" % (
        args.player, rating.value.value)
    other = Player.query().get(player_id=opponent.player_id.value)
    print "\tPlayer %s with rating %d." % (other.nickname.value,
                                           opponent.value.value)
示例#4
0
    def best_worst_elo():
        ranks = Rank_Elo.query().all()
        ranks = sorted(ranks, key=lambda x: x.value.value, reverse=best)

        # the table to print out
        table = [['Rank', 'Rating', 'Nick', 'Firstname', 'Lastname', 'ID']]
        #print "Rank\tRating\tNick\tForename\tSurname\tid"

        for i in range(min(args.amount, len(ranks))):
            player = Player().query().get(player_id=ranks[i].player_id.value)
            #print "%d\t%d\t%s\t%s,\t%s\t%s" % (i + 1, ranks[i].value.value,
            #    player.nickname.value, player.firstname.value,
            #    player.lastname.value, player.player_id.value)
            table.append([
                i + 1, ranks[i].value.value, player.nickname.value,
                player.firstname.value, player.lastname.value,
                player.player_id.value
            ])
        utils.print_table(table)
示例#5
0
def match(args):
    def match_elo(rating):
        ratings = Rank_Elo.query().all()
        best = None
        deviation = 99999999
        for r in ratings:
            if (best is None or abs(r.value.value - rating.value.value) <
                deviation) and r.player_id.value != rating.player_id.value:
                best = r
                deviation = abs(r.value.value - rating.value.value)
        return best

    def match_glicko(rating):
        print "Not implemented yet"
        return None

    """
    Finds the best opponent for a given player.

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

    match_funcs = {'elo': match_elo, 'glicko': match_glicko}

    rating = utils.get_rating(args)
    if rating is None:
        print "Player %s is not known." % args.player
        return

    print "Looking for the best opponent for player %s..." % args.player

    opponent = match_funcs[args.algorithm](rating)

    if opponent is None:
        print "No opponent found."
        return

    print "Best opponent for player %s with rating %d is:" % (args.player,
        rating.value.value)
    other = Player.query().get(player_id=opponent.player_id.value)
    print "\tPlayer %s with rating %d." % (other.nickname.value,
        opponent.value.value)
示例#6
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"])
示例#7
0
def predict(args):
    """
    Reads match constellations from an input file and writes the
    results to a specified output file.

    :param args: A list with arguments from the argument parser
    :type args: namespace
    """
    if os.path.abspath(args.ifile) == os.path.abspath(args.ofile):
        print "You tried to overwrite your input with your output file."
        print "Aborted."
        return

    if args.algorithm == "glicko":
        print "Not implemented yet"
        return

    try:
        modes = {True: "incremental", False: "non-incremental"}
        print "Predicting the matches in %s mode" % modes[args.incremental]
        print "Open %s and write into %s..." % (args.ifile, args.ofile)
        csvfile, reader, hasHeader = utils.get_csv(args.ifile)
        ofile = open(args.ofile, 'w')
        line = 0

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

        # 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 for
        # faster access and on-the-fly calculation of new elo values
        ratings = Rank_Elo.query().all()
        rdict = {}
        for r in ratings:
            player = Player.query().get(player_id=r.player_id.value)
            rdict[player.nickname.value] = r

        for row in reader:
            if line != 0 or (line == 0 and not hasHeader):
                ratings = (rdict.get(row[1], None), rdict.get(row[2], None))
                if ratings[0] is None or ratings[1] is None:
                    continue
                value1 = ratings[0].value.value
                value2 = ratings[1].value.value

                if (value1 > value2):
                    outcome = 1
                elif (value1 < value2):
                    outcome = 0
                else:
                    outcome = 0.5

                if args.incremental:
                    result = elo.elo1on1(value1, value2, outcome, k, func)
                    ratings[0].value = result[0]
                    ratings[1].value = result[1]

                ofile.write("%s,%s,%s,%s\n" %
                            (row[0], row[1], row[2], str(outcome)))
            elif line == 0 and hasHeader:
                ofile.write('"%s","%s","%s","Statistically most possible ' \
                            'outcome"\n' % (row[0], row[1], row[2]))
            if line % 13 == 0:
                sys.stdout.write("\rWrote %d entries to the out file" % line)
                sys.stdout.flush()
            line = line + 1
        print "\rWrote %d entries to the out file" % (line -
                                                      (1 if hasHeader else 0))
        csvfile.close()
        ofile.close()

    except csv.Error:
        print "Error importing %s in line %d" % (args.ifile, line)
    except IOError:
        print "One file is missing. Either %s or %s" % (args.ifile, args.ofile)
示例#8
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()
示例#9
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"])
示例#10
0
def predict(args):
    """
    Reads match constellations from an input file and writes the
    results to a specified output file.

    :param args: A list with arguments from the argument parser
    :type args: namespace
    """
    if os.path.abspath(args.ifile) == os.path.abspath(args.ofile):
        print "You tried to overwrite your input with your output file."
        print "Aborted."
        return

    if args.algorithm == "glicko":
        print "Not implemented yet"
        return

    try:
        modes = {True: "incremental", False: "non-incremental"}
        print "Predicting the matches in %s mode" % modes[args.incremental]
        print "Open %s and write into %s..." % (args.ifile, args.ofile)
        csvfile, reader, hasHeader = utils.get_csv(args.ifile)
        ofile = open(args.ofile, 'w')
        line = 0

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

        # 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 for
        # faster access and on-the-fly calculation of new elo values
        ratings = Rank_Elo.query().all()
        rdict = {}
        for r in ratings:
            player = Player.query().get(player_id=r.player_id.value)
            rdict[player.nickname.value] = r

        for row in reader:
            if line != 0 or (line == 0 and not hasHeader):
                ratings = (rdict.get(row[1], None), rdict.get(row[2], None))
                if ratings[0] is None or ratings[1] is None:
                    continue
                value1 = ratings[0].value.value
                value2 = ratings[1].value.value

                if (value1 > value2):
                    outcome = 1
                elif (value1 < value2):
                    outcome = 0
                else:
                    outcome = 0.5

                if args.incremental:
                    result = elo.elo1on1(value1, value2, outcome, k, func)
                    ratings[0].value = result[0]
                    ratings[1].value = result[1]

                ofile.write("%s,%s,%s,%s\n" % (row[0], row[1], row[2],
                    str(outcome)))
            elif line == 0 and hasHeader:
                ofile.write('"%s","%s","%s","Statistically most possible ' \
                            'outcome"\n' % (row[0], row[1], row[2]))
            if line % 13 == 0:
                sys.stdout.write("\rWrote %d entries to the out file" % line)
                sys.stdout.flush()
            line = line + 1
        print "\rWrote %d entries to the out file" % (
            line - (1 if hasHeader else 0))
        csvfile.close()
        ofile.close()

    except csv.Error:
        print "Error importing %s in line %d" % (args.ifile, line)
    except IOError:
        print "One file is missing. Either %s or %s" % (args.ifile, args.ofile)