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
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"
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()
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()
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."
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"])
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."
#!/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()
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"])
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."